typescriptwebpacktree-shakingdate-fns

date-fns 2 - can't get tree-shaking to work


I'm having trouble figuring how date-fns v.2 tree-shaking feature works...

To help me with it, I've made a really simple project using:

the test contains 2 files, one acting as the "library", the other acting as the code to run, and it is as simple as...

import ParseDate from './parse-date'

const parse = new ParseDate();
const result = parse.getExpirationDate({ months: 3 });

console.log(result);

but the issue is, though I'm only asking to work with 6 libraries using the tree-shaking use

import { addYears, addMonths, addWeeks, addDays, addHours, addMinutes } from 'date-fns';

from their docs:

// Without tree-shaking:
import format from 'date-fns/format'
import parse from 'date-fns/parse'

// With tree-shaking:
import { format, parse } from 'date-fns'

webpack is bundling the entire date-fns library, being the result of the 2 files, 726Kb !!

> npm run build

> date_fns_test@1.0.0 build C:\Users\balexandre\date_fns_test
> tsc && webpack

Hash: 419a712549fc2309f21e
Version: webpack 4.39.3
Time: 820ms
Built at: 2019-09-09 17:27:36
    Asset     Size  Chunks             Chunk Names
bundle.js  726 KiB    main  [emitted]  main
Entrypoint main = bundle.js
chunk {main} bundle.js (main) 441 KiB [entry] [rendered]
    > ./src/index.js main
 [./src/index.js] 410 bytes {main} [depth 0] [built]
     single entry ./src/index.js  main
 [./src/parse-date.js] 1.27 KiB {main} [depth 1] [built]
     cjs require ./parse-date [./src/index.js] 6:35-58
     + 212 hidden modules

What am I missing? ...must be a simple thing but I've run out of ideas :(

The project can be found on GitHub for easy review (and git pull) :)


Solution

  • To make tree-shaking work you have to configure TypeScript to compile to ES Modules instead of CommonJS and also enable production mode in webpack:

    With this setup you'll have just 1Kb build:

    $ size-limit dist/bundle.js 
    
      Package size: 724 B
      With all dependencies, minified and gzipped
    

    Here's a patch for your repo:

    diff --git a/tsconfig.json b/tsconfig.json
    index 42d6d90..b64255d 100644
    --- a/tsconfig.json
    +++ b/tsconfig.json
    @@ -1,7 +1,7 @@
     {
         "compilerOptions": {
           /* Basic Options */
    -      "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
    +      "target": "es2015",                       /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
           "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
           // "lib": [],                             /* Specify library files to be included in the compilation. */
            "allowJs": false,                        /* Allow javascript files to be compiled. */
    diff --git a/webpack.config.js b/webpack.config.js
    index 8ccbc94..1419137 100644
    --- a/webpack.config.js
    +++ b/webpack.config.js
    @@ -3,7 +3,7 @@ const path = require('path');
    
     const config = {
       entry: './src/index.js',
    -  mode: 'development',
    +  mode: 'production',
       stats: 'verbose',
       output: {
           path: path.resolve(__dirname, 'dist'),