Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

记一次 webpack 打包体积优化 #6

Open
shhider opened this issue Nov 22, 2019 · 0 comments
Open

记一次 webpack 打包体积优化 #6

shhider opened this issue Nov 22, 2019 · 0 comments

Comments

@shhider
Copy link
Owner

shhider commented Nov 22, 2019

迁移过来,2018 年 2 月的文章

手头做的项目开发得差不多了,而打包配置是一开始粗略配置的,不大的项目打包出来得6MB+,所以现在必须进行优化。

打包结果分析

执行命令 webpack --profile --json > stats.json ,可以将打包过程的详细信息以 json 格式记录到文件中。依据该文件,webpack-bundle-analyzerWebpack Chart 等分析工具会以可视化的形式展示打包过程和结果。

webpackbundleanalyzer

如果不想用这些额外工具,通过命令 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_ENVproduction

不少库会按开发环境(development)和生产环境(production)提供不同的文件,主要是为了开发模式下的调试,也会因此有文件体积上的差别。用于生产环境的打包,设置其为production后,这些库会提供最小体积的文件。

plugins: [
    // ...
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify('production')
      }
    }),
    // ...
]

css-loader

css-loader 在 webpack 默认不开启压缩,需要设置 css-loader?minimize

module: {
    // ...
    {
      test: /\.css$/,
      use: ExtractTextPlugin.extract({
        fallback: 'style-loader',
        use: 'css-loader?minimize'
      })
    }
    // ...
}

大头——antd (ant design)

因为并没有使用 antd 的所有组件,所以按需加载是必需的。根据其文档(按需加载 - Ant Design),需要安装 bable 插件 babel-plugin-import ,并在 babel 配置中添加:

{
    // ...
    "plugins": [
        ["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }],
        // ...
    ]
}

在我配置过程中,libraryDirectory 配置的不同也会有较大影响,但按目前文档来看貌似没有影响,待我确认后再做记录。

=== 2018-02-23 更新 ===

看来bable-plugin-import这几天有更新,现在配置项 libraryDirectory 的默认值时 lib,即使用通过 require (commonjs) 引用模块的文件。而先前我在配置的时候并没有默认值,如果没有显示配置 libraryDirectory,打包结果会出现重复的内容。

采用了 es6 module 的项目建议配置 libraryDirectoryes,即使用通过 import (es6 module) 引用模块的文件。这种情况打包后的体积要更小一些。

=== end ===

这里还有很重要一点,babel-plugin-import 要求 antd 不能被提取为公共模块 vendors,否则就无法实现按需加载。尚不清楚是 babel 插件的原因,还是这个插件单独的原因。

moment

moment 库的体积开销主要是 i18n 文件,配置 webpack 将用不到 i18n 文件不打包即可。

plugins: [
    new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /zh-cn/),
]

看上去很轻量的 lodash

lodash看上去就是一些工具函数,应该是很轻量的,然而一次全部加载下来要达到500KB,因此也需要按需加载。它的按需加载还比较麻烦。

lodash为每个方法单独提供了库,但这种方式在实际使用中并不灵活,所以这种最「干净」的方法不建议使用。

像 antd 一样,lodash 也有 babel 插件用于按需加载——babel-plugin-lodash

{
    // ...
    "plugins": [
        "lodash",
        // ...
    ]
}

同样,lodash 就不能提取到公共模块了。

最后

打包结果的体积开销主要就是以上几项。经过优化后,体积下降至1.5MB以内,还是很客观的。不过 antd 依然占据大头,后续会考虑把 antd 替换掉,毕竟用到的组件不多。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant