2021年1月8日(webpack项目优化)


查看项目分析图
  • webpack-bundle-analyzer
    image-20210108113653639

    image-20210108113714529

2.多进程

  • HappyPack

注:由于HappyPack作者对js的兴趣逐步丢失,所以之后维护将变少,webpack4及之后推荐使用thread-loader

使用HappyPack优化打包速度,比如我们有多个模块,交给HappyPack,在webpack compiler的run方法之后,进程就会到达HappyPackHappyPack会做一些初始化,初始化之后会创建一个线程池,线程池会将构建任务里面的模块进行分配,那么一个happyPack的一个线程池会包括多个线程,这时候线程池的这些线程会各自去处理其中的模块以及它的依赖,处理完成之后会有一个通信的过程,会将处理好的资源传输给HappyPack的一个主进程,完成整个的一个构建过程。

module.exports = override(
  addWebpackModuleRule({
    test: /\.jsx$/, //
    use: [
      // 'babel-loader'
      'happypack/loader',
    ]
  }),
  alter_config()
)
const alter_config = () => (config) => {
  config.plugins.push(
    /* 多线程编译 */
    new HappyPack({
      loaders: ['babel-loader']
    }),
  )
  return config
}
  • thread-loader

原理:与HappyPack类似,每次webpack解析一个模块,thread-loader会将它及它的依赖分配给worker进程中

module.exports = override(
 addWebpackModuleRule({
    test: /.jsx$/, // 对所有js后缀的文件进行编译
    include: resolve('src'), // 表示在src目录下的.js文件都要进行一下使用的loader
    use: [
      'babel-loader',
      {
        loader: 'thread-loader',
        options: {
          workers: 3,
        }
      }
    ]
  })
)
  • hard-source-webpack-plugin

    抛弃 DLL,选择hard-source-webpack-plugin

    dll的概念: 其实是做缓存

    所谓动态链接,就是把一些经常会共享的代码制作成 DLL 档,当可执行文件调用到 DLL 档内的函数时,Windows 操作系统才会把 DLL 档加载存储器内,DLL 档本身的结构就是可执行档,当程序有需求时函数才进行链接。透过动态链接方式,存储器浪费的情形将可大幅降低。

    将dll和缓存进行对比可以发现:

    缓存 DLL
    把常用的文件存储到内存或硬盘中 把公共代码打包为dll文件放到硬盘中
    再次打包时,直接取读取缓存 再次打包时,读取dll文件,不重新打包
    加载时间减少 打包时间减少

2.并行压缩,移除console.log

  • terser-webpack-plugin

    但是因为是webpack4,所以在运用 terser-webpack-plugin 的时候一定要注意版本号,刚开始就是用的5.0.1,要用"terser-webpack-plugin": "^4.2.3",版本,否则会报一个 ‘javascript’ 的错误

config.optimization = {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        parallel: 4, // 开启并行压缩
        terserOptions: {
          ecma: undefined,
          warnings: false,
          parse: {},
          compress: {
            drop_console: true,
            drop_debugger: false,
            pure_funcs: ['console.log'], // 移除console
          }
        }
      })
    ]
 }

3.图片压缩

  • image-webpack-loader

    在这里url-loader image-webpack-loader 不能一起使用,否则会导致图片出不来

    使用file-loader搭配,一定要先写file-loader才能使用 image-webpack-loader

    通过yarn安装image-webpack-loader会导致Error: Cannot find module ‘gifsicle’,使用cnpm安装即可

    addWebpackModuleRule({
       test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
       use: [
         {
           loader: 'file-loader',
           options: {
             name: '[name]_[hash:8].[ext]',
           },
         },
         {
           loader: 'image-webpack-loader',
           options: {
             mozjpeg: {
               progressive: true,
               quality: 50
             },
             optipng: {
               enabled: false,
             },
             pngquant: {
               quality: [0.5, 0.65],
               speed: 4
             },
             gifsicle: {
               interlaced: false,
             },
             webp: {
               quality: 100
             }
           }
         }
       ]
     })

4.去掉无用的css

使用插件purgecss-webpack-plugin,直接使用配置很简单文档

如果使用css modules,需要配置白名单whitelistPatterns

如果开启css modules,配合babel-plugin-react-css-modules一起使用,需要特别注意css的引入方式是import styles from "./index.module.css";,而不能省略变量styles

如果import "./index.module.css";这样的话,模块话的css会被忽略。

new MiniCssExtractPlugin({
       filename: "css/[name].[contenthash:8].css",
       chunkFilename: "css/[name].[contenthash:8].css"
   }),
   // 放在MiniCssExtractPlugin之后
   new PurgecssWebpackPlugin({
       // collectWhitelistPatternsChildren: () => {
       //     return [/^purify-/];
       // },
       // whitelist: () => {
       //     return [/\.module\.(css|scss|sass)$/];
       // },
       whitelistPatterns: () => {
           return [/^purify-/];
       },
       paths: () => glob.sync([`${paths.appSrc}/**/*`], { nodir: true })
   })

5.代码分割

webpack4废弃了CommonsChunkPlugin插件,使用optimization.splitChunksoptimization.runtimeChunk来代替,原因可以参考《webpack4:连奏中的进化》一文。关于runtimeChunk参数,有的文章说是提取出入口chunk中的runtime部分,形成一个单独的文件,由于这部分不常变化,可以利用缓存。google开发者社区的博文是这样描述的

const code_slicing = () => (config) => {
  config.devtool = false
  config.optimization = {
    minimizer: [
      new TerserPlugin({
        parallel: 4, // 开启并行压缩
        cache: true,
        terserOptions: {
          ecma: undefined,
          warnings: false,
          parse: {},
          compress: {
            drop_console: true,
            drop_debugger: false,
            pure_funcs: ['console.log'], // 移除console
          }
        }
      })
    ],
    splitChunks: {
      cacheGroups: {
        earth: {
          chunks: 'all',
          priority: 1,
          test: /[\\/]node_modules[\\/]xt-earth[\\/]/,
          name: 'Earth',
          minSize: 0,
          minChunks: 1
        },
        editor: {
          chunks: 'all',
          priority: 1,
          test: /[\\/]node_modules[\\/]monaco-editor[\\/]/,
          name: 'Editor',
          minSize: 0,
          minChunks: 1
        },
        echarts: {
          chunks: 'all',
          priority: 1,
          test: /(echarts|echarts-for-react|echarts-gl)/,
          name: 'Echarts',
          minSize: 0,
          minChunks: 1
        },
        babel: {
          chunks: 'all',
          priority: 1,
          test: /[\\/]node_modules[\\/]@babel[\\/]/,
          name: 'Babel',
          minSize: 0,
          minChunks: 1
        }
      }
    }
  }
  return config
}

6.代码压缩

new CompressionWebpackPlugin({
      filename: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'), // 匹配文件名
      threshold: 10240, // 对10K以上的数据进行压缩
      minRatio: 0.8,
      deleteOriginalAssets: false // 是否删除源文件
    })

需要在nginx配置

输入图片说明


Author: wxy
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint policy. If reproduced, please indicate source wxy !
  TOC