Webpack | 如何提升构建速度,进行体积优化?

这是我参与更文挑战的第29天,活动详情查看:更文挑战

[webpack系列文章连载中…]

上篇文章,已经说明了进行优化的前期准备,如何查看构建统计信息、速度分析,以及体积分析。这篇文章就写写,如何进行具体的优化。

1. 构建速度优化

1. 使用高版本工具的福利

高版本的webpack和node.js能带来构建时间上的提升,以webpack4为例。

  1. V8上的优化,提升了代码执行效率。比如:

  2. for of 替换 forEach | Map和Set替换Object | Includes替换indexOf

  3. 默认使用更快的md4 hash算法

  4. webpack AST可以直接从loader传递给AST,减少间隙时间

  5. 使用字符串方法替换正则表达式

2. 资源并行解析

这里使用thread-loader并行解析资源,大概原理是:每次webpack解析一个模块,loader会将它的依赖分配给worker线程处理。用法如下:

module.exports = {
   module:{
    rules:[
      {
      	test:/.js$/,
        include: path.resolve('src'),
        use:[
          {
            loader:'thread-loader',
               options:{
                 // 开启线程数
                 workers:3, 
                 // 额外的nodejs参数
                  workerNodeArgs: ['--max-old-space-size=1024'] 
            	 // 其他更具体参数,查看文档
               },
           },
          'babel-loader'
        ]
      }
    ]
  }
}
复制代码

说明:thread-loader要放在其他loader之前,随后的loader将在工作池中运行。每个工作程序都是一个单独的node.js进程,其开销约为600毫秒,并且进程间通信也有开销,因此这个loader只能用于一些昂贵的操作。

3. 并行压缩

  1. 使用 parallel-uglify-plugin 插件
const ParallelUglifyPlugin = require('parallel-uglify-plugin')
// 更详细配置查看官网
module.exports = {
	plugins:[
  	new ParallelUglifyPlugin({
    	uglifyJS:{
      	output:{
        	beautify:false,
          comments:false
        },
        compress:{
        	warning:false,
          drop_console:true
        }
      }
    })
  ]
}
复制代码
  1. 使用uglifyjs-webpack-plugin插件
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
  plugins:[
     new UglifyJsPlugin({
      parallel:true,  // 开启并行
    	uglifyOptions:{
        // 其他配置查看官网
      }
    })
  ]
}
复制代码
  1. 使用terser-webpack-plugin插件
const TerserPlugin = require('terser-webpack-plugin')
module.exports = {
	optimization:{
  	minimizer:[
    	new TerserPlugin({
      	 parallel:3  // 开启并行数
      })
    ]
  }
}
复制代码

2. 构建体积优化

1. 分包:设置Externals

通过html-webpack-externals-plugins,将一些基础包通过cdn引入,不打入bundle。

const HtmlWebpackExternalsPlugins = require('html-webpack-externals-plugins')
module.exports = {
    new HtmlWebpackExternalsPlugins({
        externals:[
           {
  	      module:'vue',
  	      entry:'//***/vue.min.js',
              global:'Vue'
	   }
  	]
   })
}
复制代码

这种方式构建完成后,会在index.html创建多个script标签,分别引入对应的库(配置的entry).

2. 分包:预编译资源模块

思路:将基础包(react/react-dom等)和业务基础包打包成一个文件

方法:使用DLLPlugin插件进行分包,DllReferencePlugin对maniffest.json引用

实现流程如下:

  1. 根目录编写配置文件:webpack.dll.config.js
const path = require("path");
const webpack = require("webpack");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

const library =  {
  vue: ["vue", "vue-router", "vuex"], // 值越多,抽取的文件越大,键为抽取的文件名
  others: ["axios", "js-cookie"],
}

// dll文件存放的目录
const dllPath = "public/baselib";
module.exports = {
  // 入口文件
  entry: {
    ...library
  },
  // 输出文件
  output: {
    path: path.join(__dirname, dllPath),
    filename: "MyDll.[name].js",
    library: "[name]_[hash]"
  },
  plugins: [
    // 清除上一打包产生的dll文件
    new CleanWebpackPlugin(),
    new webpack.DllPlugin({
      path: path.join(__dirname, dllPath, "[name]-manifest.json"),
      name: "[name]_[hash]"
    })
  ]
};
复制代码
  1. package.json添加打包命令
{
   "scripts":{
     "dll":"webpack -p --progress --config ./webpack.dll.conf.js"
  }	
}
复制代码
  1. 执行命令,产生文件

执行命令:npm run dll,会产生如下文件

public/baselib/vue-manifest.json

public/baselib/others-manifest.json

public/baselib/MyDll.vue.js

public/baselib/others.js
复制代码
  1. webpack配置DllReferencePlugin
const path = require("path");
const webpack = require("webpack");
const dllPath = "./public/baselib/";

// 应当处理出公共配置
const library =  {
  vue: ["vue", "vue-router", "vuex"], 
  others: ["axios", "js-cookie"],
}

plugins: [
   ...Object.keys(library).map(name => {
     return new webpack.DllReferencePlugin({
       context: ".",
       manifest: path.join(dllPath, `${name}-manifest.json`)
     });
   })
]
复制代码

模板文件引入js

<body>
  <!--文件路径中<%= BASE_URL %>为vue cli 3中读取根目录的写法,使用其他框架的请使用自己的写法-->
  <script src="https://juejin.cn/post/<%= BASE_URL %>baselib/MyDll.vue.js"></script>
  <script src="https://juejin.cn/post/<%= BASE_URL %>baselib/MyDll.others.js"></script>
</body>
复制代码

只要运行np run dll命令打包一次即可,若配置有更改,则需重新打包以及引入文件。

3. 总结

至此我们完成了webpack速度优化和体积优化策略的学习,当然还有设计其他优化策略,下一章继续。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享