WebPack基础入门(四):打包优化提升打包速度

1,562 阅读4分钟

推荐阅读

WebPack基础入门(一):万物皆可webpack

WebPack基础入门(二):React项目配置

WebPack基础入门(三):配置eslint

WebPack基础入门(四):打包优化提升打包速度

WebPack基础入门(五):多环境配置

Webpack基础入门(六):多页面打包

前言

前面介绍了打包react项目一些常规的配置,接下来两章内容都会从打包优化方方面着手,介绍在打包的过程中如何提升打包速度,从而引入不同环境(development,production)下是否需要这些优化。

正文

优化不能盲目的进行,想要考虑从那几个方面着手,下面是我总结几个方面

  1. Node,Npm,Yarn的更新
  2. 合理使用resolve
  3. 在较少的模块下使用loader
  4. 保证plugins的可靠性

说明一下:

  1. 在打包项目的时候使用的是yarn 或者 npm 每一次包管理器的迭代都会更新内部的一些依赖,其底层需要依赖node.js 环境。所以Node,Npm,Yarn的更新对打包速度是有影响的。
  2. resolve的mainFiles,alias, extensions 字段都是为了在编码的过程中检索代码重复编写,其内部进行了文件的查找。但是如果使用太多会导致在打包的过程中不断的查找文件,降低速度。
  3. loader 是解释代码,对于js 或者 jsx 文件我们没有必要对 node_moudles 下的这类文件进行再次编译
  4. 对于项目的打包优化,其主要是使用插件进行优化,能够合理的使用可靠性比较高的插件对于提升速度是必不可少的。

综上所述可以看到优化的主力军就是plugins,所以我将会介绍几种插件的使用。

clean-webpack-plugin

先看一下 output 的一个配置

output: {
    filename: '[name].[hash:8].js',
    path: path.resolve(process.cwd(), 'dist'),
  },
# 每次打包就会在打包文件名后跟一个 8 位的 hash 值,所以每次打包生产的文件名都不一样,这样就会导致 dist 文件夹下有非常多的上次打包文件。

为了解决上述文件可以使用 clean-webpack-plugin 插件,他的作用就是每次打包就会清理指定的文件夹。

  1. 安装
npm install --save-dev clean-webpack-plugin
  1. 使用
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports={
  # ...
  output: {
    filename: '[name].[hash:8].js',
    path: path.resolve(process.cwd(), 'dist'),
  },
  plugins: [
     new HtmlWebpackPlugin({
      template: './index.html',
     }),
     # 会清空 output 配置的 path 目录
     new CleanWebpackPlugin(),
  ],
}

第三方模块打包

先看一段配置

optimization: {
    runtimeChunk: {
      name: 'runtime'
    },
    usedExports: true,
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10,
          name: 'vendors'
        }
      }
    }
  },
# 这段配置的意思是把第三方模块都打包到一个指定的文件。如果没有配置这个选项,会把所有的打包项输入到 output 的 filename 文件里面.

但是上面的配置纯在一个缺陷,每次打包都会对第三方进行打包。对于实际开发中,对于类似于react,react-dom等模块,只需要打包一次就可以,每次打包的引入只需要引入第一次打包的第三方模块即可。

我们可以增加一个webpack.dll.js配置文件

const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const webpack = require('webpack')

module.exports = {
  mode: 'production',
  entry: {
    vendors: ['react', 'react-dom', 'loadsh']
  },
  output: {
    filename: '[name].dll.js',
    path: path.resolve(__dirname, '../dll'),
    library: '[name]'
  },
  plugins: [
    new webpack.DllPlugin({
      name: '[name]',
      path: path.resolve(__dirname, '../dll/[name].manifest.json'),
    })
  ]
}
# 会将 react react-dom lodash 打包输入至 dll 目录下 vendors.dll.js, 使用 webpack.DllPlugin 这个插件会生成一个名为 manifest.json 的文件,这个文件是用来让 DLLReferencePlugin 映射到相关的依赖上去的, 

此时在执行打包的过程中,会发现我们打包的 vendors.dll.js并不会引入到打包生成的index.js 文件里面,所以我们要用到另外一个插件add-asset-html-webpack-plugin

webpack.config.js 中添加如下配置

plugins:[
  new AddAssetHtmlPlugin({
      filepath: path.resolve(__dirname, '../dll/vendors.dll.js'),
    }),
]

这样就引入了打包后的vendors.dll.js。查看wenpack 官方文档就会发现 webpack.DllPluginDllReferencePlugin是要同时使用。

webpack.config.js 中添加如下配置

plugins:[
    new webpack.DllReferencePlugin({
      manifest: path.resolve(__dirname, '../dll/vendors.manifest.json'),
    })
]

package.json中添加如下脚本

"build:dll": "webpack --config ./config/webpack.dll.js"
# --config 后面填写配置文件路径

执行 npm run build:dll 或者 yarn build 就会把react,react-dom,loadsh模块单独打包。

这样我们只需要执行一遍 build ,再次执行 build 的时候,就会在vendors.manifest.json文件里面找是否已经打包过,如果打包过就不在进行打包,使用上一次,如果没有就去nodo_modules里面查找依赖打包。

结束

本文到这里已经结束了,当然打包优化是一个不断探索和研究的过程,远不止我写的这么点,还有 按需引入,多进程打包,合理使用 sourceMap,本机配置等多个方面因素的影响。也就不去写了,下一节我们将探讨不同环境下的不同配置。