为生产构建 webpack - 最小化依赖

Building webpack for production - minified dependencies

假设 npm 上有一个名为 "awesomepackage" 的模块。我可以通过 package.json 将其注册为我的应用程序的依赖项,如下所示:

npm i --save awesomepackage

检查我的 node_modules 文件夹,我看到一个名为 "awesomepackage" 的文件夹,如下所示:

- index.js
- package.json
- README.md
- lib/
    - awesomepackage.min.js

我可以像这样在我自己的应用程序中使用这个包:

import {AwesomeThing} from 'awesomepackage';

我的问题:

当我使用 webpack 构建我的应用程序时,我的最终 bundle.js 始终包含来自 node_modules/awesomepackage/index.js 的源代码 - 无论我设置了任何环境变量(例如 NODE_ENV=production)。

有什么方法可以告诉 webpack 使用预构建文件(例如 node_modules/awesomepackage/lib/awesomepackage.min.js)如果它们是作为 NPM 包的一部分提供的,而不是从源代码重新构建?

我在 webpack 配置中看到了 that use resolve.aliasnoParse 的解决方案,这些解决方案具有指向缩小源文件的硬编码路径,但这在很大程度上并没有违背使用 npm 和网页包?我不想硬编码和维护每个依赖项的缩小构建文件的路径!

我来到这里是因为当我添加 moment.js 时我的 bundle.js 跳了 2.5mb - 它缩小了 167kb,包括所有语言环境,但其中源代码包含 2mb 的测试。

编辑

显然,它不仅仅是在最后缩小最终的 bundle.js 文件。例如:为什么有人想要在最终生产代码中包含数百个不必要的依赖单元测试?他们没有。这就是为什么大多数库都提供 dist(或类似的)文件夹作为其 npm 模块的一部分的原因。

为什么不缩小整个 webpack bundle.js? (source)

webpack -p for building once for production (minification)

可能比尝试找到一些方法来使用单个包的缩小版本更容易。

让我们考虑一下你的时刻套餐。

您可以随时使用

import moment from 'node_modules/moment/min/moment-with-locales.min.js'

但这不是一个好主意。


你不应该在 webpack 中使用压缩文件

如果你使用

import moment from 'moment';

它将从源代码构建模块。但是如果你在 webpack 配置文件中有缩小过程,它不应该比运送的 .min.js 文件大很多。通常您自己的构建可能比原始构建更小 .min.js!


暂时实验

我在添加 moment 后测量了我的 bundle.js 的额外大小,它的 190 kB 和原始 moment/min/moment-with-locales.min.js 大小是 207 kB。你的2.5MB大概是你加了地图(在我的配置中有地图moment权重2.7MB)你可以分析一下it is build with all locales - webpack 可以打印此统计信息(大小在缩小之前):

 [373] ./~/moment/moment.js 135 kB {0} [built]
 [374] ./~/moment/locale/af.js 2.62 kB {0} [optional] [built]
 [375] ./~/moment/locale/ar-ma.js 2.12 kB {0} [optional] [built]
 [376] ./~/moment/locale/ar-sa.js 3.16 kB {0} [optional] [built]
 [377] ./~/moment/locale/ar-tn.js 1.97 kB {0} [optional] [built]
 [378] ./~/moment/locale/ar.js 4.59 kB {0} [optional] [built]
 [379] ./~/moment/locale/az.js 3.35 kB {0} [optional] [built]
 [380] ./~/moment/locale/be.js 4.86 kB {0} [optional] [built]
 [381] ./~/moment/locale/bg.js 3.1 kB {0} [optional] [built]
 [382] ./~/moment/locale/bn.js 3.62 kB {0} [optional] [built]
 [383] ./~/moment/locale/bo.js 3.87 kB {0} [optional] [built]
 [384] ./~/moment/locale/br.js 3.44 kB {0} [optional] [built]
 [385] ./~/moment/locale/bs.js 4.7 kB {0} [optional] [built]
 [386] ./~/moment/locale/ca.js 2.97 kB {0} [optional] [built]
 [387] ./~/moment/locale/cs.js 6.4 kB {0} [optional] [built]
 [388] ./~/moment/locale/cv.js 2.33 kB {0} [optional] [built]
 [389] ./~/moment/locale/cy.js 2.92 kB {0} [optional] [built]
 [390] ./~/moment/locale/da.js 2.07 kB {0} [optional] [built]
 [391] ./~/moment/locale/de-at.js 3.03 kB {0} [optional] [built]
 [392] ./~/moment/locale/de.js 2.95 kB {0} [optional] [built]
 [393] ./~/moment/locale/dv.js 2.69 kB {0} [optional] [built]
 [394] ./~/moment/locale/el.js 3.73 kB {0} [optional] [built]
 [395] ./~/moment/locale/en-au.js 2.32 kB {0} [optional] [built]
 [396] ./~/moment/locale/en-ca.js 2.2 kB {0} [optional] [built]
 [397] ./~/moment/locale/en-gb.js 2.38 kB {0} [optional] [built]
 [398] ./~/moment/locale/en-ie.js 2.37 kB {0} [optional] [built]
 [399] ./~/moment/locale/en-nz.js 2.32 kB {0} [optional] [built]
 [400] ./~/moment/locale/eo.js 2.67 kB {0} [optional] [built]
 [401] ./~/moment/locale/es.js 2.97 kB {0} [optional] [built]
 [402] ./~/moment/locale/et.js 3.14 kB {0} [optional] [built]
 [403] ./~/moment/locale/eu.js 2.39 kB {0} [optional] [built]
 [404] ./~/moment/locale/fa.js 3.27 kB {0} [optional] [built]
 [405] ./~/moment/locale/fi.js 3.86 kB {0} [optional] [built]
 [406] ./~/moment/locale/fo.js 2.1 kB {0} [optional] [built]
 [407] ./~/moment/locale/fr-ca.js 2.09 kB {0} [optional] [built]
 [408] ./~/moment/locale/fr-ch.js 2.25 kB {0} [optional] [built]
 [409] ./~/moment/locale/fr.js 2.24 kB {0} [optional] [built]
 [410] ./~/moment/locale/fy.js 2.64 kB {0} [optional] [built]
 [411] ./~/moment/locale/gd.js 2.63 kB {0} [optional] [built]
 [412] ./~/moment/locale/gl.js 2.77 kB {0} [optional] [built]
 [413] ./~/moment/locale/he.js 3.41 kB {0} [optional] [built]
 [414] ./~/moment/locale/hi.js 3.88 kB {0} [optional] [built]
 [415] ./~/moment/locale/hr.js 4.83 kB {0} [optional] [built]
 [416] ./~/moment/locale/hu.js 4 kB {0} [optional] [built]
 [417] ./~/moment/locale/hy-am.js 3.22 kB {0} [optional] [built]
 [418] ./~/moment/locale/id.js 2.94 kB {0} [optional] [built]
 [419] ./~/moment/locale/is.js 4.43 kB {0} [optional] [built]
 [420] ./~/moment/locale/it.js 2.46 kB {0} [optional] [built]
 [421] ./~/moment/locale/ja.js 2.21 kB {0} [optional] [built]
 [422] ./~/moment/locale/jv.js 2.94 kB {0} [optional] [built]
 [423] ./~/moment/locale/ka.js 3.15 kB {0} [optional] [built]
 [424] ./~/moment/locale/kk.js 2.68 kB {0} [optional] [built]
 [425] ./~/moment/locale/km.js 2.02 kB {0} [optional] [built]
 [426] ./~/moment/locale/ko.js 2 kB {0} [optional] [built]
 [427] ./~/moment/locale/ky.js 2.69 kB {0} [optional] [built]
 [428] ./~/moment/locale/lb.js 4.92 kB {0} [optional] [built]
 [429] ./~/moment/locale/lo.js 2.32 kB {0} [optional] [built]
 [430] ./~/moment/locale/lt.js 4.37 kB {0} [optional] [built]
 [431] ./~/moment/locale/lv.js 3.9 kB {0} [optional] [built]
 [432] ./~/moment/locale/me.js 4.1 kB {0} [optional] [built]
 [433] ./~/moment/locale/mk.js 3.11 kB {0} [optional] [built]
 [434] ./~/moment/locale/ml.js 2.81 kB {0} [optional] [built]
 [435] ./~/moment/locale/mr.js 5.39 kB {0} [optional] [built]
 [436] ./~/moment/locale/ms-my.js 2.86 kB {0} [optional] [built]
 [437] ./~/moment/locale/ms.js 2.85 kB {0} [optional] [built]
 [438] ./~/moment/locale/my.js 2.73 kB {0} [optional] [built]
 [439] ./~/moment/locale/nb.js 2.23 kB {0} [optional] [built]
 [440] ./~/moment/locale/ne.js 3.81 kB {0} [optional] [built]
 [441] ./~/moment/locale/nl.js 2.63 kB {0} [optional] [built]
 [442] ./~/moment/locale/nn.js 2.09 kB {0} [optional] [built]
 [443] ./~/moment/locale/pa-in.js 4.01 kB {0} [optional] [built]
 [444] ./~/moment/locale/pl.js 3.94 kB {0} [optional] [built]
 [445] ./~/moment/locale/pt-br.js 2.23 kB {0} [optional] [built]
 [446] ./~/moment/locale/pt.js 2.34 kB {0} [optional] [built]
 [447] ./~/moment/locale/ro.js 2.61 kB {0} [optional] [built]
 [448] ./~/moment/locale/ru.js 7.08 kB {0} [optional] [built]
 [449] ./~/moment/locale/se.js 2.23 kB {0} [optional] [built]
 [450] ./~/moment/locale/si.js 2.43 kB {0} [optional] [built]
 [451] ./~/moment/locale/sk.js 5.49 kB {0} [optional] [built]
 [452] ./~/moment/locale/sl.js 6.16 kB {0} [optional] [built]
 [453] ./~/moment/locale/sq.js 2.45 kB {0} [optional] [built]
 [454] ./~/moment/locale/sr-cyrl.js 4.1 kB {0} [optional] [built]
 [455] ./~/moment/locale/sr.js 4.09 kB {0} [optional] [built]
 [456] ./~/moment/locale/ss.js 3.12 kB {0} [optional] [built]
 [457] ./~/moment/locale/sv.js 2.4 kB {0} [optional] [built]
 [458] ./~/moment/locale/sw.js 2.08 kB {0} [optional] [built]
 [459] ./~/moment/locale/ta.js 4.21 kB {0} [optional] [built]
 [460] ./~/moment/locale/te.js 3.09 kB {0} [optional] [built]
 [461] ./~/moment/locale/th.js 2.4 kB {0} [optional] [built]
 [462] ./~/moment/locale/tl-ph.js 2.14 kB {0} [optional] [built]
 [463] ./~/moment/locale/tlh.js 4.09 kB {0} [optional] [built]
 [464] ./~/moment/locale/tr.js 2.9 kB {0} [optional] [built]
 [465] ./~/moment/locale/tzl.js 3.59 kB {0} [optional] [built]
 [466] ./~/moment/locale/tzm-latn.js 2.11 kB {0} [optional] [built]
 [467] ./~/moment/locale/tzm.js 2.06 kB {0} [optional] [built]
 [468] ./~/moment/locale/uk.js 5.4 kB {0} [optional] [built]
 [469] ./~/moment/locale/uz.js 2.03 kB {0} [optional] [built]
 [470] ./~/moment/locale/vi.js 2.71 kB {0} [optional] [built]
 [471] ./~/moment/locale/x-pseudo.js 2.5 kB {0} [optional] [built]
 [472] ./~/moment/locale/zh-cn.js 4.35 kB {0} [optional] [built]
 [473] ./~/moment/locale/zh-tw.js 3.12 kB {0} [optional] [built]
 [474] ./~/moment/locale ^\.\/.*$ 2.41 kB {0} [optional] [built]

那么为什么您的自定义版本更小?您可以使用更积极的缩小。我的构建给了我这个信息(可能在这一点上它减轻了一些重量):

Condition always true [./~/moment/moment.js:8,0]
Condition always true [./~/moment/locale/af.js:6,0]
Condition always true [./~/moment/locale/ar-ma.js:7,0]
Condition always true [./~/moment/locale/ar-sa.js:6,0]
Condition always true [./~/moment/locale/ar-tn.js:5,0]
Condition always true [./~/moment/locale/ar.js:8,0]
Condition always true [./~/moment/locale/az.js:6,0]
Condition always true [./~/moment/locale/be.js:8,0]
Condition always true [./~/moment/locale/bg.js:6,0]
Condition always true [./~/moment/locale/bn.js:6,0]
Condition always true [./~/moment/locale/bo.js:6,0]
Condition always true [./~/moment/locale/br.js:6,0]
Condition always true [./~/moment/locale/bs.js:7,0]
Condition always true [./~/moment/locale/ca.js:6,0]
Condition always true [./~/moment/locale/cs.js:6,0]
Dropping unreachable code [./~/moment/locale/cs.js:31,0]
Dropping unreachable code [./~/moment/locale/cs.js:40,0]
Dropping unreachable code [./~/moment/locale/cs.js:49,0]
Dropping unreachable code [./~/moment/locale/cs.js:58,0]
Dropping unreachable code [./~/moment/locale/cs.js:67,0]
Condition always true [./~/moment/locale/cv.js:6,0]
Condition always true [./~/moment/locale/cy.js:6,0]
Condition always true [./~/moment/locale/da.js:6,0]
Condition always true [./~/moment/locale/de-at.js:9,0]
Condition always true [./~/moment/locale/de.js:8,0]
Condition always true [./~/moment/locale/dv.js:6,0]
Condition always true [./~/moment/locale/el.js:6,0]
Condition always true [./~/moment/locale/en-au.js:5,0]
Condition always true [./~/moment/locale/en-ca.js:6,0]
Condition always true [./~/moment/locale/en-gb.js:6,0]
Condition always true [./~/moment/locale/en-ie.js:6,0]
Condition always true [./~/moment/locale/en-nz.js:5,0]
Condition always true [./~/moment/locale/eo.js:8,0]
Condition always true [./~/moment/locale/es.js:6,0]
Condition always true [./~/moment/locale/et.js:7,0]
Condition always true [./~/moment/locale/eu.js:6,0]
Condition always true [./~/moment/locale/fa.js:6,0]
Condition always true [./~/moment/locale/fi.js:6,0]
Condition always true [./~/moment/locale/fo.js:6,0]
Condition always true [./~/moment/locale/fr-ca.js:6,0]
Condition always true [./~/moment/locale/fr-ch.js:6,0]
Condition always true [./~/moment/locale/fr.js:6,0]
Condition always true [./~/moment/locale/fy.js:6,0]
Condition always true [./~/moment/locale/gd.js:6,0]
Condition always true [./~/moment/locale/gl.js:6,0]
Condition always true [./~/moment/locale/he.js:8,0]
Condition always true [./~/moment/locale/hi.js:6,0]
Condition always true [./~/moment/locale/hr.js:6,0]
Condition always true [./~/moment/locale/hu.js:6,0]
Dropping unused variable suffix [./~/moment/locale/hu.js:16,0]
Condition always true [./~/moment/locale/hy-am.js:6,0]
Condition always true [./~/moment/locale/id.js:7,0]
Condition always true [./~/moment/locale/is.js:6,0]
Condition always true [./~/moment/locale/it.js:7,0]
Condition always true [./~/moment/locale/ja.js:6,0]
Condition always true [./~/moment/locale/jv.js:7,0]
Condition always true [./~/moment/locale/ka.js:6,0]
Condition always true [./~/moment/locale/kk.js:6,0]
Condition always true [./~/moment/locale/km.js:6,0]
Condition always true [./~/moment/locale/ko.js:10,0]
Condition always true [./~/moment/locale/ky.js:6,0]
Condition always true [./~/moment/locale/lb.js:6,0]
Condition always true [./~/moment/locale/lo.js:6,0]
Condition always true [./~/moment/locale/lt.js:6,0]
Condition always true [./~/moment/locale/lv.js:7,0]
Condition always true [./~/moment/locale/me.js:6,0]
Condition always true [./~/moment/locale/mk.js:6,0]
Condition always true [./~/moment/locale/ml.js:6,0]
Condition always true [./~/moment/locale/mr.js:7,0]
Condition always true [./~/moment/locale/ms-my.js:6,0]
Condition always true [./~/moment/locale/ms.js:6,0]
Condition always true [./~/moment/locale/my.js:6,0]
Condition always true [./~/moment/locale/nb.js:7,0]
Condition always true [./~/moment/locale/ne.js:6,0]
Condition always true [./~/moment/locale/nl.js:6,0]
Condition always true [./~/moment/locale/nn.js:6,0]
Condition always true [./~/moment/locale/pa-in.js:6,0]
Condition always true [./~/moment/locale/pl.js:6,0]
Condition always true [./~/moment/locale/pt-br.js:6,0]
Condition always true [./~/moment/locale/pt.js:6,0]
Condition always true [./~/moment/locale/ro.js:7,0]
Condition always true [./~/moment/locale/ru.js:8,0]
Condition always true [./~/moment/locale/se.js:6,0]
Condition always true [./~/moment/locale/si.js:6,0]
Condition always true [./~/moment/locale/sk.js:7,0]
Dropping unreachable code [./~/moment/locale/sk.js:32,0]
Dropping unreachable code [./~/moment/locale/sk.js:41,0]
Dropping unreachable code [./~/moment/locale/sk.js:50,0]
Dropping unreachable code [./~/moment/locale/sk.js:59,0]
Dropping unreachable code [./~/moment/locale/sk.js:68,0]
Condition always true [./~/moment/locale/sl.js:6,0]
Condition always true [./~/moment/locale/sq.js:8,0]
Condition always true [./~/moment/locale/sr-cyrl.js:6,0]
Condition always true [./~/moment/locale/sr.js:6,0]
Condition always true [./~/moment/locale/ss.js:6,0]
Condition always true [./~/moment/locale/sv.js:6,0]
Condition always true [./~/moment/locale/sw.js:6,0]
Condition always true [./~/moment/locale/ta.js:6,0]
Condition always true [./~/moment/locale/te.js:6,0]
Condition always true [./~/moment/locale/th.js:6,0]
Condition always true [./~/moment/locale/tl-ph.js:6,0]
Condition always true [./~/moment/locale/tlh.js:6,0]
Condition always true [./~/moment/locale/tr.js:7,0]
Condition always true [./~/moment/locale/tzl.js:6,0]
Condition always true [./~/moment/locale/tzm-latn.js:6,0]
Condition always true [./~/moment/locale/tzm.js:6,0]
Condition always true [./~/moment/locale/uk.js:7,0]
Condition always true [./~/moment/locale/uz.js:6,0]
Condition always true [./~/moment/locale/vi.js:6,0]
Condition always true [./~/moment/locale/x-pseudo.js:6,0]
Condition always true [./~/moment/locale/zh-cn.js:7,0]
Condition always true [./~/moment/locale/zh-tw.js:6,0]

重用通用模块

Moment 不是突出 webpack 最强大功能的最佳模块 - 重用通用模块(因为 moment 不使用依赖项).

假设您的应用程序使用 3 个模块,并且每个模块都有一些依赖项。

                   size

module1            20 kB 
  dependencies
    - moduleA      10 kB 
    - moduleB      15 kB
    - moduleC      5  kB
module1.min        50 kB

module2            10 kB 
  dependencies
    - moduleA      10 kB 
    - moduleD      5  kB
module2.min        25 kB

module3            30 kB 
  dependencies
    - moduleA      10 kB 
    - moduleC      5  kB
module3.min        45 kB

如果您只使用这 3 个模块的 .min 版本,您将向您的应用程序添加 50 kB + 25 kB + 45 kB = 120 kB

                   size

module1            20 kB 
  dependencies
    - moduleA      10 kB  
    - moduleB      15 kB 
    - moduleC      5  kB 
module1.min        50 kB  <-- this

module2            10 kB  
  dependencies
    - moduleA      10 kB 
    - moduleD      5  kB 
module2.min        25 kB  <-- this

module3            30 kB  
  dependencies
    - moduleA      10 kB 
    - moduleC      5  kB
module3.min        45 kB  <-- this

另一方面,如果您将使用源文件构建,公共模块将只添加一次。不像以前 moduleA 被包含 3 次和 moduleC 2 次。 这次将添加到您的应用程序:

                   size

module1            20 kB  <-- this
  dependencies
    - moduleA      10 kB  <-- this
    - moduleB      15 kB  <-- this
    - moduleC      5  kB  <-- this
module1.min        50 kB

module2            10 kB  <-- this
  dependencies
    - moduleA      10 kB 
    - moduleD      5  kB  <-- this
module2.min        25 kB

module3            30 kB  <-- this
  dependencies
    - moduleA      10 kB 
    - moduleC      5  kB
module3.min        45 kB

最后,通过这种方法,您可以将 95 kB 添加到您的应用程序中。