likes
comments
collection
share

记录一次 Webpack 优化

作者站长头像
站长
· 阅读数 19

开篇

本次优化主要做的是 Webpack 打包资源体积大小的优化,目的是为了解决单页面应用首页加载白屏时间过长问题。

下面会根据分析优化的步骤一一记录分享。

分析 package.json 依赖

  • 清除无用依赖(比如,项目中 import 导入了有个模块,但是没有引用 - 开发者的代码不规范操作);
  • 对包进行分类:
    • 只在开发环境所使用的依赖(babel、webpack)安装在 devDependencies 之下;

    • 需要进行打包部署的程序运行代码(react、antd)安装在 dependencies 之下;

    • 这个规范在一个 npm 线上包 的开发尤其重要。

配置 babel-plugin-import

现在的打包工具(Webpack)和组件库(Antd)都已支持 tree-shaking 的优化,无需再配置按需引入,但如果不支持 tree-shaking,则还是需要配置 babel-plugin-import 来优化 UI 组件库的打包体积。

  • 安装:
npm install babel-plugin-import -D
  • 使用(BabelV6):
// .babelrc
{
    ...
    plugins: [
        ...
        [
          "import", [
            { "libraryName": "antd", "libraryDirectory": "lib", style: "css" },
            { "libraryName": "antd-mobile", "libraryDirectory": "lib", style: "css" },
          ]
        ]
    ]
}

如果使用的是 BabelV7 版本,配置多个按需加载模块时,可以配置多个 import 实例:

// .babelrc
"plugins": [
  ["import", { "libraryName": "antd", "libraryDirectory": "lib"}, "antd"],
  ["import", { "libraryName": "antd-mobile", "libraryDirectory": "lib"}, "antd-mobile"]
]

优化 moment.js

如果项目中有用到 moment.js 这个库,它默认会引入所有的多语种资源文件,我们可以进行配置,只引入我们需要的语种资源:

// webpack.config.js
const webpack = require('webpack');
module.exports = {
  ...
  plugins: [
    // 只加载 `moment/locale/zh-cn.js` 和 `moment/locale/en-xx.js`
    new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /zh-cn|en/),
  ]
}

externals 外部扩展

对于项目中使用到的一些依赖,我们不希望在打包的时候将它们打包进去,而是在 html 模板中使用 script 标签对其引入,我们可以在 webpack 配置中对相关模块进行“忽略”。

// webpack.config.js
module.export = {
  // ...
  externals: {
    jquery: 'jQuery',
  },
}

在 html 模板中引入 cdn 资源:

<body>
  <div id="root"></div>
  // 资源将 jQuery 绑定到了 window 全局上
  <script src="https://code.jquery.com/jquery-3.1.0.js"></script>
</body>

vendor 抽离(分包)

将一个体积较大的打包资源文件,拆分为多个小资源文件进行引入,借助于浏览器同时并发加载多个资源的特性来优化资源加载时长。

// webpack.config.js
module.exports = {
  ...
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'scripts/js/[name].js', // 入口文件的命名
    chunkFilename: "scripts/js/[name].js?v=[chunkhash:8]", // 分包的命名
  },
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        common: {
          chunks: "all",
          minChunks: 2,
          name: 'chunk-common',
          enforce: true,
          priority: 5
        },
        vendor: {
          name: 'chunk-vendors',
          test: /[\\/]node_modules[\\/]/,
          priority: 10,
          chunks: 'initial'
        },
        antd: {
          name: 'chunk-antd',
          priority: 20,
          test: /[\\/]node_modules[\\/]_?antd(.*)/
        },
      }
    }
  },
}

打包分析工具

上面所做的都是已知可以优化的项,我们可以借助于打包资源分析工具,它提供了一个每个模块的体积大小可视化展示,可以针对某个依赖模块进行优化。

  • 安装:
npm install webpack-bundle-analyzer -D
  • webpack 配置:
// webpack.config.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
  ...
  plugins: [
    ...
    new BundleAnalyzerPlugin(),
  ]
}
  • 启动:
npm run build(打包)
or
npm start(启动 devServer)

最后

经过这轮优化,体会更深的该是开发者们对自身开发的要求,比如尽量避免出现以下类似情况:

  • 掌握打包工具的正确使用方式。比如项目中配置多个 babel-plugim-import 的方式不对,导致没有按需引入没有生效;(可以查看包的 npm 相关文档的使用介绍)
  • 避免为实现某一个小功能,而引入了一个非常大的依赖包,在做功能实现时,一定要深思熟虑,选择最优方案。