webpack性能优化——DLL

本文介绍如何使用Webpack的DLL特性来优化构建过程,通过分离第三方库和应用代码,减少打包时间并提升加载速度。

Webpack性能优化的方式有很多种,本文之所以将 dll 单独讲解,是因为 dll 是一种最简单粗暴并且极其有效的优化方式。

在通常的打包过程中,你所引用的诸如:jquery、bootstrap、react、react-router、redux、antd、vue、vue-router、vuex 等等众多库也会被打包进 bundle 文件中。由于这些库的内容基本不会发生改变,每次打包加入它们无疑是一种巨大的性能浪费。

Dll 的技术就是在第一次时将所有引入的库打包成一个 dll.js 的文件,将自己编写的内容打包为 bundle.js 文件,这样之后的打包只用处理 bundle 部分。

 

以一个 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 文件方便对 Dll.js 中的模块进行引用。

要注意的是,执行 webpack 命令是默认执行该目录下名为 webpack.config.js 或者 webpackfile.js 的文件。所以需要通过 --config 指令手动指定该文件,最后加入 -p 指令将 Dll.js 压缩。

$ 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 文件中的文件都被 delegated(委派) ,而不是直接打进 bundle 文件中。

这样我们就将所有的资源完成打包,生成的 dist 目录如下:

 

不过 dist 文件夹要想作为一个完整的工程还少一个 html 文件,我创建了一个名为 pack.js 的文件,使用 nodejs 的 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 标签,并在引用文件后添加时间戳。

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

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

在执行 webpack -p 打包后,输入下面命令运行 pack.js,就会在 dist 目录下生成 html 文件。

$ node pack.js

内容如下:

<!-- .... -->
<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

 

感谢你的浏览,希望能有所帮助。

<think>嗯,用户这次的问题是关于Webpack前端性能优化的具体方法。之前已经讨论过Loader和Plugin的区别,现在用户显然是想深入实践层面。 用户可能正在实际项目中遇到性能瓶颈,需要可落地的解决方案。从引用[1]和[4]来看,用户特别关注大型Vue项目的优化场景。不过引用[3]提醒得很对——不能只盯着配置参数,要抓住核心思想。 我注意到四个引用材料都强调了几点共性:资源压缩、代码分割、懒加载和构建速度优化。这应该是回答的主线。尤其引用[2]提到的"渐进式优化"思路很实用,可以重点展开。 用户提供的引用材料虽然有些零碎,但正好覆盖了优化的不同维度:引用[1]讲整体思路,引用[2]侧重运行时,引用[3]关注构建过程,引用[4]补充Vue特例。需要把这些拼成完整图谱。 在技术细节上要特别注意:引用[3]警告过webpack更新频繁,所以提到具体API时得标注版本兼容性。比如SplitChunksPlugin在webpack4和5的配置差异很大。 最后考虑设计"相关问题"时,要延续用户之前对Loader/Plugin的兴趣点。比如Tree Shaking和Scope Hoisting的实现原理,既关联之前话题,又是性能优化重点。</think>Webpack 前端性能优化主要通过 **减少资源体积、提升加载速度和优化构建效率** 三个维度实现。以下是核心方法及实践策略: --- ### 一、减少资源体积(减小 Bundle 大小) 1. **代码压缩(TerserPlugin)** 压缩 JS、CSS 和 HTML 文件,删除注释和空白符。 ```javascript // webpack.config.js const TerserPlugin = require("terser-webpack-plugin"); module.exports = { optimization: { minimizer: [new TerserPlugin()] } }; ``` 2. **Tree Shaking** 移除未使用的 JS 代码(需 ES6 模块化语法)。 ```javascript optimization: { usedExports: true } // 标记未使用代码 ``` 3. **作用域提升(Scope Hoisting)** 合并模块作用域,减少闭包数量。 ```javascript optimization: { concatenateModules: true } ``` 4. **图片压缩(ImageMinimizerPlugin)** 自动压缩 PNG/JPEG 等图片资源。 ```javascript const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin"); plugins: [new ImageMinimizerPlugin({ minimizer: { implementation: ImageMinimizerPlugin.squooshMinify } })] ``` --- ### 二、提升加载速度(优化资源加载) 1. **代码分割(Code Splitting)** 拆分代码为多个 Chunk,按需加载。 ```javascript optimization: { splitChunks: { chunks: "all" } // 分离公共模块 } ``` 2. **懒加载(Lazy Loading)** 动态导入非首屏资源(如路由组件)。 ```javascript // Vue/React 中 const LazyComponent = () => import("./LazyComponent.vue"); ``` 3. **预加载关键资源(Preload/Prefetch)** 优先加载关键资源(如首屏 CSS)。 ```html <!-- 配合 HtmlWebpackPlugin 使用 --> <link rel="preload" href="main.css" as="style"> ``` 4. **CDN 加速第三方库** 将 `react`、`lodash` 等库通过 CDN 引入,减小 Bundle 体积。 ```javascript externals: { react: "React" } // 排除打包 ``` --- ### 三、优化构建效率(加快开发/打包速度) 1. **缓存 Loader 结果(Cache)** 缓存 Babel 等 Loader 的转换结果。 ```javascript module: { rules: [{ test: /\.js$/, loader: "babel-loader", options: { cacheDirectory: true } // 启用缓存 }] } ``` 2. **多进程构建(Thread-loader)** 用多进程处理耗时的 Loader(如 Babel)。 ```javascript rules: [{ test: /\.js$/, use: ["thread-loader", "babel-loader"] // 多进程编译 }] ``` 3. **限制 Loader 范围(exclude/include)** 避免编译 `node_modules` 中的文件。 ```javascript rules: [{ test: /\.js$/, exclude: /node_modules/, // 排除目录 loader: "babel-loader" }] ``` 4. **DLL 预编译** 将第三方库预先打包为 DLL 文件(适合长期不变的库)。 ```javascript // 使用 DllPluginDllReferencePlugin plugins: [new webpack.DllReferencePlugin({ manifest: require("./dll/manifest.json") })] ``` --- ### 四、高级优化策略 1. **Gzip 压缩** 使用 `CompressionWebpackPlugin` 生成 `.gz` 文件。 ```javascript const CompressionPlugin = require("compression-webpack-plugin"); plugins: [new CompressionPlugin({ algorithm: "gzip" })] ``` 2. **分析构建产物(Bundle Analyzer)** 可视化分析 Bundle 组成。 ```javascript const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin; plugins: [new BundleAnalyzerPlugin()] ``` 3. **持久化缓存(Cache)** Webpack 5+ 内置文件系统缓存。 ```javascript module.exports = { cache: { type: "filesystem" } }; ``` --- ### 五、Vue 项目特化优化(引用[4]) 1. **异步组件 + Suspense** 拆分路由组件为异步模块。 2. **`vue-router` 懒加载** ```javascript { path: "/home", component: () => import("./Home.vue") } ``` 3. **按需引入 UI 库(如 Element-Plus)** 避免全量导入。 --- ### 优化效果验证 - 使用 `webpack-bundle-analyzer` 分析 Bundle 组成 - Lighthouse 评分检测加载性能 - 对比构建时间:`speed-measure-webpack-plugin` > **核心原则**:优先优化首屏资源(Critical Resources),采用渐进式策略[^2][^3]。例如先解决 Bundle 过大的问题,再实施懒加载,最后优化构建速度。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值