提升webpack构建速度(二)

分离基础脚本

一、 使用DllPluginDllReferencePlugin,将不会经常更新的模块提前进行构建(有更新的话再构建一次),每次构建只是针对于变化的模块。总构建时间理论上会减少(视情况而定)。。。

项目结构:

首先在build文件夹下新增webpack.dll.conf.js文件:使用DllPlugin

const webpack = require("webpack")
const path = require('path')
const os = require('os')
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const resolve = (dir) => path.join(__dirname, '..', dir);

const env = process.env.NODE_ENV === 'testing'
  ? require('../config/test.env')
  : require('../config/prod.env')

module.exports = {
  entry: {
    vendor: ['v-viewer', 'vuescroll', 'vue-i18n', 'bignumber.js'] // 这4个模块不经常更新
  },
  output: {
    path: resolve('dll_static'),
    library: '_dll_[name]_[hash]',
    filename: '_dll_[name]_[hash].js'
  },
  plugins: [
    // 去除开发环境提醒:You are running Vue in development mode.
    new webpack.DefinePlugin({
      'process.env': env
    }),
    new CleanWebpackPlugin(),
    new webpack.DllPlugin({
      name: '_dll_[name]_[hash]', //和output.library中一致,值就是输出的manifest.json中的 name值
      path: path.join(__dirname, '../dll_static', '[name].manifest.json')
    }),
    new UglifyJsPlugin({
      uglifyOptions: {
        compress: {
          warnings: true,
          drop_debugger: true,
          drop_console: true
        }
      },
      sourceMap: false,
      parallel: os.cpus().length - 1
    }),
  ]
}

webpack.base.conf.js文件中加入:使用DllReferencePlugin

plugins: [
    // 引用动态链接库
    new webpack.DllReferencePlugin({
      manifest: path.resolve(__dirname, '../dll_static/vendor.manifest.json')
    }),
  ]

package.json文件scripts中新增一项 "build:dll": "webpack --config build/webpack.dll.conf.js"

在项目根目录下运行 npm run build:dll 后,会生成dll_static文件夹:包括所有模块(js)和映射关系文件(json),如项目结构图中的dll_static。由于这些dll.js没有包含在bundle.js中,我们在入口文件中直接用是会报错的,我们需要将dll.js插入到index.html文件中去(注:需要在bundle.js之前)

  • 在构建完成后,手动将dll.js写入index.html文件中去
  • 使用add-asset-html-webpack-plugin插件
  • 修改index.html入口文件(使用htmlWebpackPlugin.options

add-asset-html-webpack-plugin

// 文件动态添加到html中
new AddAssetHtmlPlugin([
      {
        filepath: path.resolve(__dirname, '../dll_static/*.js'),
        outputPath: 'dll_static',
        publicPath: 'dll_static',
        includeSourcemap: false,
        hash: true,
      }
]),

// 结果如下
<script type=text/javascript src=./static/js/manifest.a41c74cbe64915cdf684.js></script>
<script type=text/javascript src=./static/js/vendor.7a69e6c902f4c682ee3e.js></script>
<script type=text/javascript src=./static/js/app.65ee13921c33c87b3f8d.js></script>
<script src=static/dll_static/_dll_vendor_9f972cb316fca89ce8c5.js?=9f972cb316fca89ce8c5></script>

这个插件老是将代码插入到body最底部,导致上述模块undefined。网上说可以,我目前是没成功。。。

利用htmlWebpackPlugin.options

webpack.base.conf.jswebpack.prod.conf.js文件中加入:

// 注:①
new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../dll_static'),
        to: config.dev.assetsSubDirectory + '/dll_static',
        ignore: ['**/*.json'] // 不复制json文件
      }
])

new HtmlWebpackPlugin({
      // dll存着dll.js的引用地址
      dll: (function () {
              let name = require(path.resolve(__dirname, `../dll_static/vendor.manifest.json`)).name

              return `static/dll_static/${name}.js`
      })()
})

html-webpack-plugin的入口文件index.html文件中写入: <script src="<%= htmlWebpackPlugin.options.dll %>"></script>,最终效果:

<script src=static/dll_static/_dll_vendor_9f972cb316fca89ce8c5.js></script>

①:我们上文提到的理论构建时间较少,才用DllPlugin时候比全量编译构建时间只少了2s-3s左右,原因分析:虽然我们每次不构建dll.js,但是每次构建的时候我们需要复制dll.js到指定目录(dev为以项目根目录起的内存文件系统,dev为硬盘文件系统),我开发用的电脑系统是windows 10,经常性的磁盘占用率100%(机械硬盘),感觉复制dll.js文件占用了好多时间。。。(全量编译时间 - 复制时间 = 2s-3s),其实没减少多少,如果换成ssd的话应该效果会提升。

二、 externals,使用外部脚本引入方式,需修改index.html入口文件

修改webpack.base.conf.js文件

module.exports = {
      externals: {
          "BMap": "BMap",
          'vue': 'Vue',
          'vue-router': 'VueRouter',
          'vuex': 'Vuex',
          'axios':'axios',
          'element-ui': 'ElementUI',
          'echarts': 'echarts'
     },    
}

index.html文件中引入

// 以cdn引入vue为例
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

总结

其实上边提到的两种方法的思路都是将公共依赖剥离出来,减少webpack构建的文件数量

参考

Webpack DllPlugin 让构建速度柔顺丝滑
webpack构建速度优化

原文地址:https://www.cnblogs.com/hanshuai/p/13523188.html