typescript - date-fns 2 - får ikke tree-shaking til å fungere


Jeg har problemer med å finne ut hvordan date-fns v.2 tree-shaking-funksjonen fungerer...

For å hjelpe meg med det, har jeg laget et veldig enkelt prosjekt ved å bruke:

  • date-fns 2.1.0
  • webpack 4.39.3
  • typescript 3.6.2

testen inneholder 2 filer, en som fungerer som "biblioteket", den andre som koden som skal kjøres, og det er så enkelt som...

import ParseDate from './parse-date'

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

console.log(result);

men problemet er, selv om jeg bare ber om å jobbe med 6 biblioteker ved å bruke tre-risting

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

fra deres dokumenter:

// 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 pakker hele date-fns-biblioteket, som er resultatet av de 2 filene, 726Kb !!

> npm run build

> [email  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

Hva går jeg glipp av? ...må være en enkel ting, men jeg har kommet helt tom for ideer :(

Prosjektet kan finnes på GitHub for enkel gjennomgang (og git pull) :)

Svar #1

For å få tree-shaking til å fungere må du konfigurere TypeScript til å kompilere til ES-moduler i stedet for CommonJS, og også aktivere produksjonsmodus i webpack:

  • I tsconfig.json sett module: 'es2015'
  • I webpack.config.js sett mode: 'production'

Med denne oppsettet vil du ha bare 1Kb bygge:

size-limit dist/bundle.js 

  Package size: 724 B
  With all dependencies, minified and gzipped

Her er en patch for repoet ditt:

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'),

Svar #2

Her er en løsning for tree-shaking av date-fns-funksjonene som fungerte for meg, ved å bruke et Webpack-alias (opprinnelig nevnt i den åpne Github-issuen)

Jeg avledet løsningen fra løsningen for å få tree-shaking til å fungere for lokaler.

  1. Opprett en fil kalt for eksempel date-fns-functions.js ved siden av webpack-konfigurasjonen din hvor du vil re-eksportere funksjonene du bruker i prosjektet ditt slik som dette :
export { default as parseISO } from 'date-fns/parseISO';
export { default as formatDistanceToNow } from 'date-fns/formatDistanceToNow';
export { default as parse } from 'date-fns/parse';
...
  1. Deretter legger du til et alias i Webpack-konfigurasjonen din:
    resolve: {
        alias: {
            'date-fns$': require.resolve('./date-fns-functions.js')
        }
    },

I mitt spesifikke tilfelle, ved bruk av Nuxt.js for Webpack-bunting, la jeg dette til i nuxt.config.js i stedet:

extend (config, ctx) {
   config.resolve.alias['date-fns$'] = require.resolve('./date-fns-functions.js');
   ...
}

Hver gang du importerer noe fra date-fns, vil det slå opp importen ved å bruke aliaset, og unngå full import av hele biblioteket.

Dette løste problemet for meg og reduserte pakkestørrelsen betydelig.

Relaterte artikler