使用DllPlugin和DllReferencePlugin提高打包速度

1,962 阅读3分钟

在项目开发过程中,遇到需要优化打包速度的问题。我们可以通过分离第三库的形式优化构建速度。

在项目中我们经常会用到jquery,vue,echarts等第三方库。我们可以把这些第三库和自己的开发代码分离开来,只需要在第一次构建的时候进行打包,以后就不会再去编译这些第三方库,从而优化了打包的速度。

基础

DLLPluginDLLReferencePlugin 用某种方法实现了拆分 bundles,同时还大大提升了构建的速度。

DllPlugin

这个插件是在一个额外的独立的 webpack(一般设置为webpack.dll.config.js) 设置中创建一个只有 dll 的 bundle(dll-only-bundle)。 这个插件会生成一个名为 manifest.json 的文件,这个文件是用来让 DLLReferencePlugin 映射到相关的依赖上去的。

在给定的 path 路径下创建一个名为 manifest.json 的文件。 这个文件包含了从 requireimport 的request到模块 id 的映射。 DLLReferencePlugin 也会用到这个文件。

DllReferencePlugin

这个插件是在 webpack 主配置文件中设置的, 这个插件把只有 dll 的 bundle(们)(dll-only-bundle(s)) 引用到需要的预编译的依赖。

通过引用 dll 的 manifest 文件来把依赖的名称映射到模块的 id 上,之后再在需要的时候通过内置的 __webpack_require__ 函数来 require 他们

output.library 保持 name 的一致性。

模式(Modes)

这个插件支持两种模式,分别是作用域(scoped)映射(mapped)

作用域模式(Scoped Mode)

dll 中的内容可以在模块前缀下才能被引用,举例来说,令scope = "xyz"的话,这个 dll 中的名为 abc 的文件可以通过 require("xyz/abc") 来获取

映射模式(Mapped Mode)

dll 中的内容被映射到了当前目录下。如果一个被 require 的文件符合 dll 中的某个文件(解析之后),那么这个dll中的这个文件就会被使用。

由于这是在解析了 dll 中每个文件之后才发生的,相同的路径必须能够确保这个 dll bundle 的使用者(不一定是人,可指某些代码)有权限访问。 举例来说, 假如一个 dll bundle 中含有 loadash库 以及 文件abc, 那么 require("lodash")require("./abc") 都不会被编译进主要的 bundle文件,而是会被 dll 所使用。

用法(Usage)

  1. 搭建初始项目
目录结构:

webpack.config.js        
webpack.dll.config.js        
src            
    index.html            
    pages                
    index.js    
static
    jquery.js    
package.json
2.引入安装包 jquery,webpack,webpack-cli

npm install webpack webpack-cli html-webpack-plugin --save-dev    
npm install jquery --save    

3.搭建简单模板 运行项目

var HtmlWebpackPlugin = require('html-webpack-plugin');var path = require('path');var webpackConfig = {        mode:'development',        entry: path.resolve(__dirname,'./src/pages/index.js'),        output: {                path: path.resolve(__dirname, './dist'),                filename: 'index_bundle.js'        },        plugins: [new HtmlWebpackPlugin({                template:path.resolve(__dirname,'./src/index.html')        })]};module.exports = webpackConfig;
4.在webpack.dll.config.js编写mainfest代码

const path = require('path')const webpack = require('webpack')module.exports = {    mode: 'development',    entry: {        // 定义程序中打包公共文件的入口文件vendor.js        vendor: ['jquery'],    },    output: {        path: path.resolve('./src/dll'),        filename: '[name].dll.js',        library: '[name]_[hash]',        libraryTarget: 'this'    },    plugins: [        new webpack.DllPlugin({            // 定义程序中打包公共文件的入口文件vendor.js            context: __dirname,            // manifest.json文件的输出位置            path: path.join('./src', 'dll', '[name]-manifest.json'),            // 定义打包的公共vendor文件对外暴露的函数名            name: '[name]_[hash]'        })    ]}
// 第一次运行webpack --config webpack.dll.config.js

5.webpack.config.js修改后台的代码

...    
plugins: [        new HtmlWebpackPlugin({            template: path.resolve(__dirname, './src/index.html')        }),        // dllPlugin关联配置        // 新增代码        new webpack.DllReferencePlugin({            context: __dirname, // 跟dll.config里面DllPlugin的context一致            manifest: require('./src/dll/vendor-manifest.json')        }),    ]
...
// 第二次运行webpack

结论

运用DllPlugin插件,把第三方库分离出来,能够大幅提高打包的速度