Create react App eject后 webpack 的优化配置

Create react App 是一个官方支持的创建 react 单页应用程序的方法。它提供了一个零配置的现代构建设置。虽然开箱即用,但是开发中我们还是少不了做一些修改,下面总结了一些常用的配置,本文基于webpack4.44.2进行配置

关于eject

执行npm run eject命令会将react-scripts释放到本地项目中,可以通过修改对应的文件完成配置。同时会删除react-scripts依赖包,修改package.json中命令。命令执行完毕以后,我们就会看到本地项目中多出了scripts和config两个目录文件。同时,package.json文件命令也被修改了。

此时,如果在执行启动或者打包命令,就是直接执行的scripts目录下对应的文件了。我们可以很方便的根据需要修改对应的文件配置即可。
但值得注意的是,npm run eject命令是不可逆的,即执行之后不可恢复,这就造成了如果后续我们想通过脚手架的react-scripts包增加新的特性,比如PWA支持,是不可行的

关闭生产环境 sourcemap

通常在开发的时候,我们会配置开发环境生成 sourcemap 文件,方便调试,但是在生产环境都要关闭,避免代码泄露和打包多余文件,体积太大。
可以在项目根目录创建'.env'文件,配置如下内容:

//.env
GENERATE_SOURCEMAP=false

noParse

如果一些第三方模块没有AMD/CommonJS规范版本,可以使用 noParse 来标识这个模块,这样 webpack 会引入这些模块,但是不进行转化和解析,从而提升 webpack 的构建速度,例如:jquery 、lodash (被忽略的库不能有import、require、define的引入方式),noParse 属性的值是一个正则表达式或者是一个 function

//webpack.config.js
module.exports = {
    //...
    module: {
        noParse: /jquery|lodash/
    }
}

splitChunks抽取公共代码

splitChunks可以抽取公共代码,拆分业务代码和第三方代码库,防止打包文件过大,代码示例如下:

//webpack.config.js
optimization: {
    //...
    splitChunks: {
        chunks: 'all',
        minSize: 30000,         //字节 引入的文件大于30kb才进行分割
        minChunks: 1,           //模块至少使用次数
        automaticNameDelimiter: '~', //缓存组和生成文件名称之间的连接符
        name: true,
        cacheGroups: {
          vender: {
            name: 'vendor',
            test: /[\\/]node_modules[\\/]/,
            chunks: 'all',
            priority: 20          
          },
          react: {
            name: 'react',
            test: (module) => /react|redux/.test(module.context),
            chunks: 'initial',
            priority: 11
          },
          lodash: {
            name: 'lodash',
            test: (module) => /lodash/.test(module.context),
            chunks: 'initial',
            priority: 15 
          },
          antdm: {
            name: 'antd-mobile',
            test: (module) => /antd-mobile/.test(module.context),
            chunks: 'initial',
            priority: 12            
          }
        }
    }
}

thread-loader

webpack4 官方提供了一个thread loader,把这个 loader 放置在其他 loader 之前, 放置在这个 loader 之后的 loader 就会在一个单独的 worker池里运行,一个worker 就是一个nodeJS 进程,每个单独进程处理时间上限为600ms,各个进程的数据交换也会限制在这个时间内。
**注意:如果项目小,文件不多,无需开启多进程打包,打开反而会变慢,因为开启进程是需要花费时间的

  • 安装依赖:
cnpm install thread-loader -D
  • webpack配置:
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        include: path.resolve("src"),
        use: [
          "thread-loader",
          // your loader (e.g babel-loader)
        ]
      }
    ]
  }
}

HardSourceWebpackPlugin(用于开发环境,可以取代DllPlugin)

HardSourceWebpackPlugin 为模块提供中间缓存,缓存默认的存放路径是: node_modules/.cache/hard-source。
配置 hard-source-webpack-plugin,首次构建时间没有太大变化,但是第二次开始,构建时间大约可以节约 80%。由于生产环境的打包次数有限,所以此插件主要用于开发环境,提升打包速度。与DllPlugin相比配置更加简单,效率也更高。

  • 安装依赖:
cnpm install hard-source-webpack-plugin -D
  • webpack 的配置:
//webpack.config.js
var HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
module.exports = {
    //...
    plugins: [
        //用于开发环境
        isEnvDevelopment &&
        new HardSourceWebpackPlugin()
    ]
}

HardSourceWebpackPlugin文档
列出了一些你可能会遇到的问题以及如何解决,例如热更新失效,或者某些配置不生效等。

webpack-bundle-analyzer

借助 webpack-bundle-analyzer 可以查看哪些包的体积较大,

  • 安装依赖:
cnpm install webpack-bundle-analyzer -D
  • 配置如下:

//webpack.config.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
    //....
    plugins: [
        //...
        new BundleAnalyzerPlugin(),
    ]
}

npm run build 构建,会默认打开: http://127.0.0.1:8888/,可以看到各个包的体积,进一步使用 splitChunks 进行拆分,打包后对比,优化完成后,上线前最好删除此插件和配置

webpack自身的优化(已经默认开启,无需配置)

  • tree-shaking
    如果使用ES6的import 语法,那么在生产环境下(mode:production),会自动移除没有使用到的代码。
  • scope hosting 作用域提升
    变量提升,可以减少一些变量声明。在生产环境下,默认开启。
  • 缩小文件匹配范围(include/exclude)
  • 缓存loader的执行结果(cacheDirectory)
  • IgnorePlugin:webpack 的内置插件,作用是忽略第三方包指定目录
    例如: moment (2.24.0版本) 会将所有本地化内容和核心功能一起打包,我们就可以使用 IgnorePlugin 在打包时忽略本地化内容。
    在使用的时候,如果我们需要指定语言,那么需要我们手动的去引入语言包,例如,引入中文语言包:
    import moment from 'moment';
    import 'moment/locale/zh-cn';// 手动引入
    
  • 多进程压缩的优化:Webpack 默认使用的是 TerserWebpackPlugin,默认开启了多进程和缓存,构建时,你的项目中可以看到 terser 的缓存文件 node_modules/.cache/terser-webpack-plugin,没必要单独安装以下插件,webpack-parallel-uglify-plugin,uglifyjs-webpack-plugin 配置 parallel.
posted @ 2021-01-09 11:45  axl234  阅读(1010)  评论(0编辑  收藏  举报