DllPlugin和DllReferencePlugin

webpack4.0(六):DllPlugin和DllReferencePlugin

前言

在项目开发的时候,我们可能会发现有时候我们在打包的时候,构建速度很慢,尤其是一些我们使用的第三方库,每次都会被打包进去,大大延长了构建时间。那么我们能不能将这些稳定的库单独打包出来,这样既可以加快构建速度,还可以减少bundle的体积?

DllPlugin和DllReferencePlugin

答案是可以的。DLLPluginDLLReferencePlugin 用某种方法实现了拆分 bundles,同时还大大提升了构建的速度。
这个插件是在一个额外的独立的 webpack 设置中创建一个只有 dll 的 bundle(dll-only-bundle)。 这个插件会生成一个名为 manifest.json 的文件,这个文件是用来让 DllReferencePlugin 映射到相关的依赖上去的。

DllPlugin

该插件接受三个参数:

  • context (optional): manifest 文件中请求的上下文(context)(默认值为 webpack 的上下文(context))
  • name: 暴露出的 DLL 的函数名 ( [hash] & [name] )
  • path: manifest json 文件的绝对路径 (输出文件)

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

const path = require('path');
const webpack = require('webpack');

module.exports = {
    mode:"production",
    entry:{
        react:['react','react-dom','react-router-dom'],
        lodash:['lodash-es']
    },
    output:{
        filename:'[name].dll.js',
        path : path.resolve(__dirname,'./dll'),
        library:'_dll_[name]'
    },
    plugins:[
        new webpack.DllPlugin({
            name: "_dll_[name]",
            path: path.join(__dirname, "./dll/[name].manifest.json"),
        })
    ]
}

DllReferencePlugin

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

  • context: (绝对路径) manifest (或者是内容属性)中请求的上下文
  • manifest: 包含 contentname 的对象,或者在编译时(compilation)的一个用于加载的 JSON manifest 绝对路径
  • content (optional): 请求到模块 id 的映射 (默认值为 manifest.content)
  • name (optional): dll 暴露的地方的名称 (默认值为 manifest.name) (可参考 externals)
  • scope (optional): dll 中内容的前缀
  • sourceType (optional): dll 是如何暴露的 (libraryTarget)

这里,我们引入一个新的插件:add-asset-html-webpack-plugin。它可以将一些资源文件绑定到html上。
这里用它就是将上面打包好的第三方库绑定到html上。

webpack.config.js:

const path = require('path');
const fs = require('fs');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');

const files = fs.readdirSync(path.resolve(__dirname,'./dll'));
console.log(files);

let pluginsDll = [
    new HtmlWebpackPlugin({
        template: './src/index.html'
    })
];

files.forEach(file => {
    if(/.*\.dll.js$/.test(file)){

        pluginsDll.push(
            new AddAssetHtmlWebpackPlugin({
                filepath:path.resolve(__dirname,'./dll',file)
            })
        )
    }else if(/.*\.manifest.json$/.test(file)){
        new webpack.DllReferencePlugin({
            manifest: require(path.resolve(__dirname,'./dll',file)),
        })
    }
});

module.exports = {
    entry: './src/app.js',
    mode: "production",
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    resolve:{
        extensions:['.js','.jsx'],
        mainFiles:['main','index']
    },
    devServer:{
        contentBase:'./dist',
        open:true,
        hotOnly:true
    },
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                use: 'babel-loader'
            }
        ]
    },
    plugins: pluginsDll
}

上面的代码中,我们使用fs模块获取dll文件夹下所有的文件,通过循环遍历,将资源全部挂载到html上。
这样,当打包的时候,如果本地的dll文件下有了第三方库的文件,打包的时候就不会再次向node_module上去取。大大加快了构建速度。

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!