详解webpack性能优化——DLL

作者:巡夜人时间:2026-10-22 09:21:31浏览:298

本文详解Webpack中通过DLL(动态链接库)进行性能优化的方法。通过将Vue、React等不常变动的第三方库单独打包为Dll.js,并配合DllReferencePlugin引用,可大幅减少主包bundle.js的构建时间。文章提供了完整的配置示例、manifest.json解析及自动化HTML注入方案,帮助开发者实现高效的长期缓存与快速重编译。

DLL优化原理与优势

Webpack提供了多种性能优化手段,本文专门讲解DLL(动态链接库)技术,因为它是一种简单直接且效果显著的优化方案。

在常规打包流程中,项目引用的jquery、bootstrap、react、react-router、redux、antd、vue、vue-router、vuex等大量第三方库都会被打包进最终的bundle文件。由于这些库的内容通常保持稳定,每次构建都重新打包它们会消耗大量计算资源,造成性能浪费。

DLL技术的核心思路是:在首次构建时,将所有引入的第三方库统一打包生成一个独立的dll.js文件,而将业务代码打包为bundle.js。此后进行常规构建时,只需处理bundle.js部分,从而显著提升构建速度。

DLL配置文件编写

以Vue项目为例,首先需要创建一个名为webpack.dll.config.js的配置文件。


var path = require("path"),
  fs = require('fs'),
  webpack = require("webpack");

var vendors = [
  'vue', 
  'vue-router', 
  'vuex'
];

module.exports = {
  entry: {
    vendor: vendors
  },
  output: {
    path: path.join(__dirname, "dist"),
    filename: "Dll.js",
    library: "[name]_[hash]"
  },
  plugins: [
    new webpack.DllPlugin({
      path: path.join(__dirname, "dist", "manifest.json"),
      name: "[name]_[hash]",
      context: __dirname
    })
  ]
}; 

该配置文件的作用是将vue、vue-router和vuex合并打包为一个名为Dll.js的静态资源文件,同时生成一个manifest.json文件,用于记录模块ID以便后续引用。

需要注意的是,执行webpack命令时默认读取的是目录下的webpack.config.js或webpackfile.js文件。因此,必须通过--config参数手动指定webpack.dll.config.js文件,并追加-p参数以启用压缩优化。


$ webpack --config webpack.dll.config.js -p

执行上述命令后,项目根目录下的dist文件夹中会生成压缩后的Dll.js文件以及manifest.json文件。

manifest.json文件的内容结构如下,它为各个模块分配了唯一的ID,供后续模块引用时使用。


{
 "name": "vendor_2beb750db72b1cda4321",
 "content": {
  "./node_modules/process/browser.js": {
   "id": 0,
   "meta": {}
  },
  "./node_modules/vue-router/dist/vue-router.esm.js": {
   "id": 1,
   "meta": {
    "harmonyModule": true
   },
   "exports": [
    "default"
   ]
  },
  "./node_modules/vue/dist/vue.runtime.esm.js": {
   "id": 2,
   "meta": {
    "harmonyModule": true
   },
   "exports": [
    "default"
   ]
  },
//.......

主配置引用与构建流程

最后,需要在主配置文件webpack.config.js中添加相应的引用配置。具体做法是在plugins数组中引入DllReferencePlugin插件,并指定manifest.json文件的路径。


//...
plugins: [
  new webpack.DllReferencePlugin({
    context: __dirname,
    manifest: require('./dist/manifest.json')
  })
]

在确认webpack.dll.config.js文件执行成功后,再次运行webpack -p命令进行常规项目打包。

DLL优化原理与优势

观察打包结果可以发现,原本包含在Dll文件中的模块被标记为delegated(委派)状态,而不是直接嵌入到bundle.js文件中。

至此,所有资源均已完成打包处理,生成的dist目录结构如下所示。

DLL优化原理与优势

自动化HTML注入与部署

然而,仅生成dist文件夹还不足以构成一个完整的可运行工程,缺少HTML入口文件。为此,我编写了一个名为pack.js的Node.js脚本,利用fileSystem模块对HTML文件进行读取、修改和拷贝操作。

pack.js脚本的具体代码如下。


var fs = require('fs');

fs.readFile('./index.html', 'utf8', (err, data) => {
  if (!err) {
    var dataStr = data.toString(),
    timestamp = (new Date()).getTime();
  
    dataStr = dataStr
          .replace('bundle.js', 'bundle.js?v='+timestamp)
          .replace('<!-- dll -->', '<script src="./dist/Dll.js?v='+ timestamp +'"></script>');

    fs.writeFile('./dist/index.html', dataStr, (error) => {
      if (!error) {
        console.log('HTML file copy successfully');
      } else {
        console.log(error);
      }
    });
  } else {
    console.log(err);
  }
});

我们需要在项目的入口HTML文件中预留<!-- dll -->占位符。pack.js脚本的功能是将HTML文件复制到dist目录,并将<!-- dll -->占位符替换为引用Dll.js的script标签,同时在引用的URL后添加时间戳以强制浏览器刷新缓存。


<!-- .... -->
<body>
<div id="demo" class="container"></div>

<!-- dll -->
<script src="./bundle.js"></script>
</body>
</html>

在完成webpack -p打包后,运行以下命令执行pack.js脚本,即可在dist目录下生成最终的HTML文件。


$ node pack.js

DLL优化原理与优势

生成的HTML文件内容如下所示。


<!-- .... -->
<body>
<div id="demo" class="container"></div>

<script src="./dist/Dll.js?v=1488250309725"></script>
<script src="./bundle.js?v=1488250309725"></script>
</body>
</html>

经过上述步骤,dist文件夹已包含完整、无需手动干预且经过压缩混淆的项目文件,可直接部署到线上环境。

实际项目的模板参考地址如下。鉴于笔者同时开发React和Vue项目,因此创建了两个对应的模板,旨在后续通过yomen(yo)等脚手架工具实现自动化生成。

https://github.com/Darylxyx/generator-yx-react

https://github.com/Darylxyx/generator-yx-vue

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

作者最新文章
相关文章
更多