Vue Webpack打包优化实战:利用DllPlugin大幅缩短构建时间

作者:知秋时间:2026-10-22 12:41:01浏览:174

针对大型Vue项目Webpack打包耗时过长的问题,本文介绍了使用DllPlugin进行依赖抽离的优化方案。通过将常用第三方库预先打包为DLL文件,并在主构建中引用,可避免重复编译,显著缩短打包时间。文章详细讲解了配置步骤、文件结构处理及自动化注入方法,帮助开发者提升构建效率。

项目背景与优化动机

临近春节,公司部分同事提前返乡,留守团队依据禅道任务修复Bug。Bug修复完成后,需重新打包并部署至测试服务器供测试人员验收。由于项目体量庞大,常规打包耗时超过二十五分钟,导致效率低下。因此,团队决定实施打包优化方案(此前因工作繁忙未及执行,此次借机推进)。

Webpack作为前端项目常用的打包工具,与NPM配合使用可高效管理模块依赖。

Webpack将所有静态资源视为模块,通过配置将这些模块整合为一个bundle文件。页面只需引入该bundle.js即可加载所有静态资源,简化了资源引用流程。

接下来直接进入具体优化步骤。

首先展示项目的目录结构:

项目背景与优化动机 

这是标准的项目结构,简要说明如下:

  • build文件夹存放打包相关的配置文件。
  • config文件夹包含项目的基础配置信息。
  • dist文件夹用于存放打包后的最终文件。
  • node_modules文件夹存储项目所需的依赖包。
  • src文件夹包含项目的源代码文件。
  • static文件夹存放项目使用的静态资源文件。
  • index.html是项目的入口首页文件。
  • package.json文件记录项目的配置信息及依赖列表。
  • yarn.lock文件用于锁定使用Yarn安装的依赖版本。

打包耗时原因分析与优化思路

优化思路分析

项目打包耗时较长的主要原因包括项目整体规模大、依赖关系复杂以及组件拆分不合理。

针对上述问题,可从以下几个方面进行优化处理:

  • 实施路由级代码分割策略,仅构建业务必需模块。针对多项目合并场景(因需求相似而整合),虽简化了开发流程,但需承担由此带来的构建冗余与维护成本。
  • 针对依赖复杂的问题,当前项目依赖包多达40余个,且存在组件间重复引用。解决策略是将重用性高的依赖抽离出来单独打包。
  • 开发组件时需明确其使用场景和功能,避免功能混杂导致的冗余。

DllPlugin基础配置与依赖抽离

实际操作步骤

确定思路后,查阅Webpack文档发现DllPlugin插件是解决此问题的关键。以下是webpack.dll.config的配置代码:


var path = require("path");
var webpack = require("webpack");
function resolve (dir) {
 return path.join(__dirname, '..', dir)
}
module.exports = {
 // 你想要打包的模块的数组
 entry: {
 vendor: ['vue', 'lodash', 'vuex', 'axios', 'vue-router', 'iview', 'element-ui',
  'echarts','xlsx','jquery','vue-fullcalendar','vue-cookie','handsontable']
 },
 output: {
 path: path.join(__dirname, '../dist/vendor-dll-js'), // 打包后文件输出的位置
 filename: '[name].dll.js',
 library: '[name]_library'
 // vendor.dll.js中暴露出的全局变量名。
 // 主要是给DllPlugin中的name使用,
 // 故这里需要和webpack.DllPlugin中的`name: '[name]_library',`保持一致。
 },
 resolve: {
 extensions: ['.js', '.vue', '.json'],
 alias: {
  'vue$': 'vue/dist/vue.esm.js',
  '@': resolve('src'),
 }
 },
 plugins: [
 new webpack.DllPlugin({
  path: path.join(__dirname, '.', '[name]-manifest.json'),
  name: '[name]_library',
  context: __dirname
 }),
 // 压缩打包的文件,与该文章主线无关
 new webpack.optimize.UglifyJsPlugin({
  compress: {
  warnings: false
  }
 })
 ]
};

我们需要将项目中具有重用性的包放入vendor数组,并在output中定义输出路径。在resolve中配置解析参数,最后引入DllPlugin插件。UglifyJsPlugin用于压缩JS文件。

DllPlugin输出的path会生成一个vendor-manifest.json,用于关联ID。该文件不参与主打包,因此无需放入static目录。随后运行命令 webpack -p --progress --config build/webpack.dll.conf.js执行预打包。

成功后,static目录下会生成dll.vendor.js,根目录下会生成vendor.manifest.json 。检查这两个文件,可以看到依赖库的源码及匹配的ID信息。

依赖库抽离完成后,接下来需解决如何在开发环境和构建环境中引用这些DLL文件的问题。

此处补充DllPlugin与commonsChunk的区别:commonsChunk每次运行都会重新打包,而DllPlugin预先打包好依赖库,仅对每次修改的JS进行打包,从而提升效率。

继续上述步骤,需根据生成的json文件修改webpack.base.config配置:


const manifest = require('../vendor-manifest.json')
......
plugins: [
 new webpack.DllReferencePlugin({
  manifest
 })
 ]

然后在index.html底部添加<script src="./static/dll.vendor.js"></script>以引入DLL文件;

执行命令npm run build ,若一切正常,则表明操作正确。

自动化构建与进阶优化方案

进阶优化处理

至此,打包优化问题基本解决。但手动复制粘贴及修改index.html文件对不熟悉项目的开发者而言易出错,因此需进一步自动化处理。

思路不变,通过配置文件和命令实现自动化操作。

首先将webpack.dll.config中的entry配置项提取出来,在config文件夹下新建dll.js文件。


module.exports = {
 entry: {
 // 这里的依赖顺序必须是:对象从上往下依赖,数组从右到左依赖(如果互不依赖的可以忽略顺序)
 ui: ['iview', 'element-ui'],
 tool: ['lodash', 'jquery', 'axios', 'vue-fullcalendar'],
 vue: ['vue', 'vuex', 'vue-router', 'vue-cookie'],
 xlsx: ['xlsx'],
 echarts: ['echarts'],
 other: ['handsontable'],
 },
 outFile: '../static/dll'
};

该文件包含初始的entry配置,根据此JS打包的文件顺序遵循以下规则:

依赖顺序必须严格遵循:对象依赖从上往下,数组依赖从右到左(若无相互依赖可忽略顺序)。

若不按此顺序编写,会导致依赖错误!

随后在output中进行配置:


output: {
 path: path.join(__dirname, dllConfig.outFile), // 打包后文件输出的位置
 filename: '[name].dll.[chunkhash].js',
 library: '[name]_library'
 // 主要是给DllPlugin中的name使用,
 // 故这里需要和webpack.DllPlugin中的`name: '[name]_library',`保持一致。
 },

执行webpack -p --progress --config build/webpack.dll.conf.js 指令后,将生成如下文件结构:

项目背景与优化动机 

看到文件名后的hash值可能会感到困惑,这导致无法直接复制粘贴(我们的目标正是消除手动操作)。

为实现命令执行后无需手动复制粘贴,需使用Webpack的HtmlWebpackPlugin插件。

在plugins中配置HtmlWebpackPlugin:


new HtmlWebpackPlugin({
 filename: path.join(__dirname, '../', config.dev.index),
 template: 'index.ejs',
 inject: false
}),

在根目录添加index.ejs模板(参考ejs GitHub地址),index.ejs代码如下:


<body>
 <div id="app"></div>
 <!-- dll files will be auto injected -->
 <% for (var chunk in htmlWebpackPlugin.files.chunks) { %><script type="text/javascript" src="/<%= htmlWebpackPlugin.files.chunks[chunk].entry %>"></script>
 <% } %>
 <!-- built files will be auto injected -->
</body>

最后需在config文件夹下的index.js中进行修改:在dev配置中添加index: 'index.html';

项目执行dev或build指令前,需先执行webpack -p --progress --config build/webpack.dll.conf.js 。Dll指令执行完毕后,再运行其他操作即可顺利完成构建。

优化效果总结

总结

至此,代码打包优化过程基本结束。测试结果显示,打包时间缩短至15分钟左右,比之前快了将近10分钟,是一次非常成功的优化尝试。

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