Open shhider opened 5 years ago
迁移过来,2018 年 2 月的文章
手头做的项目开发得差不多了,而打包配置是一开始粗略配置的,不大的项目打包出来得6MB+,所以现在必须进行优化。
执行命令 webpack --profile --json > stats.json ,可以将打包过程的详细信息以 json 格式记录到文件中。依据该文件,webpack-bundle-analyzer、Webpack Chart 等分析工具会以可视化的形式展示打包过程和结果。
webpack --profile --json > stats.json
如果不想用这些额外工具,通过命令 webpack --display-modules --sort-modules-by size ,webpack 会在日志中按大小排序显示所有模块。
webpack --display-modules --sort-modules-by size
我在项目中,将第三方库基本都集中打包到一个 chunk (vendors),业务逻辑单独一个 chunk (app)。打包总体积的大头来自 vendors,其中antd占据大头(3MB+)、moment占据约500KB、提取的 css 约300KB、react-dom也是500KB+,出乎意料的是 lodash 也是500KB+。
antd
moment
react-dom
lodash
NODE_ENV
production
不少库会按开发环境(development)和生产环境(production)提供不同的文件,主要是为了开发模式下的调试,也会因此有文件体积上的差别。用于生产环境的打包,设置其为production后,这些库会提供最小体积的文件。
plugins: [ // ... new webpack.DefinePlugin({ 'process.env': { NODE_ENV: JSON.stringify('production') } }), // ... ]
css-loader 在 webpack 默认不开启压缩,需要设置 css-loader?minimize。
css-loader?minimize
module: { // ... { test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader?minimize' }) } // ... }
因为并没有使用 antd 的所有组件,所以按需加载是必需的。根据其文档(按需加载 - Ant Design),需要安装 bable 插件 babel-plugin-import,并在 babel 配置中添加:
babel-plugin-import
{ // ... "plugins": [ ["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }], // ... ] }
在我配置过程中,libraryDirectory 配置的不同也会有较大影响,但按目前文档来看貌似没有影响,待我确认后再做记录。
libraryDirectory
=== 2018-02-23 更新 ===
看来bable-plugin-import这几天有更新,现在配置项 libraryDirectory 的默认值时 lib,即使用通过 require (commonjs) 引用模块的文件。而先前我在配置的时候并没有默认值,如果没有显示配置 libraryDirectory,打包结果会出现重复的内容。
bable-plugin-import
lib
require
采用了 es6 module 的项目建议配置 libraryDirectory 为 es,即使用通过 import (es6 module) 引用模块的文件。这种情况打包后的体积要更小一些。
es
import
=== end ===
这里还有很重要一点,babel-plugin-import 要求 antd 不能被提取为公共模块 vendors,否则就无法实现按需加载。尚不清楚是 babel 插件的原因,还是这个插件单独的原因。
moment 库的体积开销主要是 i18n 文件,配置 webpack 将用不到 i18n 文件不打包即可。
plugins: [ new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /zh-cn/), ]
lodash看上去就是一些工具函数,应该是很轻量的,然而一次全部加载下来要达到500KB,因此也需要按需加载。它的按需加载还比较麻烦。
lodash为每个方法单独提供了库,但这种方式在实际使用中并不灵活,所以这种最「干净」的方法不建议使用。
像 antd 一样,lodash 也有 babel 插件用于按需加载——babel-plugin-lodash
{ // ... "plugins": [ "lodash", // ... ] }
同样,lodash 就不能提取到公共模块了。
打包结果的体积开销主要就是以上几项。经过优化后,体积下降至1.5MB以内,还是很客观的。不过 antd 依然占据大头,后续会考虑把 antd 替换掉,毕竟用到的组件不多。
手头做的项目开发得差不多了,而打包配置是一开始粗略配置的,不大的项目打包出来得6MB+,所以现在必须进行优化。
打包结果分析
执行命令
webpack --profile --json > stats.json
,可以将打包过程的详细信息以 json 格式记录到文件中。依据该文件,webpack-bundle-analyzer、Webpack Chart 等分析工具会以可视化的形式展示打包过程和结果。如果不想用这些额外工具,通过命令
webpack --display-modules --sort-modules-by size
,webpack 会在日志中按大小排序显示所有模块。我在项目中,将第三方库基本都集中打包到一个 chunk (vendors),业务逻辑单独一个 chunk (app)。打包总体积的大头来自 vendors,其中
antd
占据大头(3MB+)、moment
占据约500KB、提取的 css 约300KB、react-dom
也是500KB+,出乎意料的是lodash
也是500KB+。逐个击破
设置环境变量
NODE_ENV
为production
不少库会按开发环境(development)和生产环境(production)提供不同的文件,主要是为了开发模式下的调试,也会因此有文件体积上的差别。用于生产环境的打包,设置其为
production
后,这些库会提供最小体积的文件。css-loader
css-loader 在 webpack 默认不开启压缩,需要设置
css-loader?minimize
。大头——antd (ant design)
因为并没有使用 antd 的所有组件,所以按需加载是必需的。根据其文档(按需加载 - Ant Design),需要安装 bable 插件
babel-plugin-import
,并在 babel 配置中添加:在我配置过程中,
libraryDirectory
配置的不同也会有较大影响,但按目前文档来看貌似没有影响,待我确认后再做记录。=== 2018-02-23 更新 ===
看来
bable-plugin-import
这几天有更新,现在配置项libraryDirectory
的默认值时lib
,即使用通过require
(commonjs) 引用模块的文件。而先前我在配置的时候并没有默认值,如果没有显示配置libraryDirectory
,打包结果会出现重复的内容。采用了 es6 module 的项目建议配置
libraryDirectory
为es
,即使用通过import
(es6 module) 引用模块的文件。这种情况打包后的体积要更小一些。=== end ===
这里还有很重要一点,
babel-plugin-import
要求antd
不能被提取为公共模块 vendors,否则就无法实现按需加载。尚不清楚是 babel 插件的原因,还是这个插件单独的原因。moment
moment 库的体积开销主要是 i18n 文件,配置 webpack 将用不到 i18n 文件不打包即可。
看上去很轻量的
lodash
lodash
看上去就是一些工具函数,应该是很轻量的,然而一次全部加载下来要达到500KB,因此也需要按需加载。它的按需加载还比较麻烦。lodash
为每个方法单独提供了库,但这种方式在实际使用中并不灵活,所以这种最「干净」的方法不建议使用。像 antd 一样,
lodash
也有 babel 插件用于按需加载——babel-plugin-lodash同样,
lodash
就不能提取到公共模块了。最后
打包结果的体积开销主要就是以上几项。经过优化后,体积下降至1.5MB以内,还是很客观的。不过 antd 依然占据大头,后续会考虑把 antd 替换掉,毕竟用到的组件不多。