5.核心概念-Plugin—中-灵析社区

懒人学前端

三、DllPlugin

DllPlugin

DllPlugin 和 DllReferencePlugin 用某种方法实现了拆分 bundles,同时还大幅度提升了构建的速度。"DLL" 一词代表微软最初引入的动态链接库。

通过使用 DllPlugin 可以拆分项目中版本不经常变更的或者包大小比较大的三方依赖。将依赖拆分成单独的 bundles,这样可以提升项目打包速度、减少包体积来加快加载速度。

使用

本章中主要介绍 DllPlugin 的使用及配置,由于需要打包第三方依赖库,所以下面以 lodash 为例。

安装 lodash

npm install loadsh --save-dev

webpack.config.dll.js

新建一个 webpack.config.dll.js 文件,用来添加 dll 配置,在执行打包命令之前先生成 dll 文件。

const webpack = require('webpack');
const path = require('path');
module.exports = {
    entry: {
        lodash: ['lodash']
    },
    output: {
        filename: '[name]_dll.js',
        library: "[name]",
        path: path.resolve(__dirname, 'dist/dll')
    },
    plugins: [
        new webpack.DllPlugin({
            context: __dirname,
            path: path.join(__dirname, 'dist/dll', '[name]-mainfest.json'),
            name: '[name]'
        }),
    ]
}

在上面的配置中,entry 为项目入库文件,output 为项目输出文件名称及输出目录。其中要注意的是 output 中的 library 参数,增加 library 配置后 mainfest.json 会暴露 dll 库的全局名称。此参数定义的名称要与 DllPlugin 插件中的 name 属性定义名称一致。

在命令行执行 npx webpack --config webpack.config.dll.js 命令,打包成功后在 dist 文件下可以看到生成了一个 dll.js 一个 mainfest.json 文件。

配置

context

默认值:webpack 的 context

值类型:String

作用:生成的 manifest.json 文件中 content 对象中的文件映射地址。

webpack.config.dll.js

module.exports = {
  plugins: [
    new webpack.DllPlugin({
      // {"name":"vendors","content":{"./node_modules/lodash/lodash.js":{"id":486,"buildMeta":{}}}}
      context: __dirname // 根目录地址
      // 下面的 mainfest.json 文件将找不到 lodash.js,映射地址错误
      // {"name":"vendors","content":{"../node_modules/lodash/lodash.js":{"id":486,"buildMeta":{}}}}
      // context: 'src'
    }),
  ]
};

format

默认值:false

值类型:Boolean

作用:如果值为 true,生成的 mainfest.json 文件将被格式化。

webpack.config.dll.js

module.exports = {
  plugins: [
    new webpack.DllPlugin({
      // {"name":"vendors","content":{"./node_modules/lodash/lodash.js":{"id":486,"buildMeta":{}}}}
      format: false,
      // {
      //   "name": "vendors",
      //   "content": {
      //     "./node_modules/lodash/lodash.js": {
      //       "id": 486,
      //       "buildMeta": {}
      //     }
      //   }
      // }
      format: true
    }),
  ]
};

name

默认值:''

值类型:String

作用:生成的 mainfest.json 文件中的 name 属性值。

webpack.config.dll.js

module.exports = {
  ...
  plugins: [
    new webpack.DllPlugin({
      // {"name":"lodash-name","content":{"./node_modules/lodash/lodash.js":{"id":486,"buildMeta":{}}}}
      name: "lodash-name"
    })
  ]
};

path

默认值:无(必须)

值类型:String

作用:生成 mainfest.json 文件的路径。

webpack.config.dll.js

module.exports = {
  ...
  plugins: [
    new webpack.DllPlugin({
      // 在根目录的 dist/dll 文件夹下生成 [name]-mainfest.json
      path: path.join(__dirname, 'dist/dll', '[name]-mainfest.json'),
    })
  ]
};

entryOnly

默认值:true

值类型:Boolean

作用:如果为 true,则仅暴露入口。

webpack.config.dll.js

module.exports = {
  ...
  plugins: [
    new DllPlugin({
      entryOnly: false
    })
  ]
};

建议 DllPlugin 只在 entryOnly: true 时使用,否则 DLL 中的 tree shaking 将无法工作,因为所有 exports 均可使用。

type

类型:"var" | "module" | "assign" |"assign-properties" | "this" | "window" | "self" | "global" | "commonjs" | "commonjs2" | "commonjs-module" |"commonjs-static" | "amd" | "amd-require" | "umd" | "umd2" | "jsonp" | "system"

作用:配置 dll 库暴露的方式。

webpack.config.dll.js

module.exports = {
  ...
  plugins: [
    new DllPlugin({
      // {"name":"lodash-name","type":"window","content":{"./node_modules/lodash/lodash.js":{"id":486,"buildMeta":{}}}}
      type: 'window'
    })
  ]
};

总结

此章节演示了 DllPlugin 的用法和包含的配置参数。生成的 dll.js 和 mainfest.json 文件,在下个 DllReferencePlugin 章节来展示如何使用。

四、DllReferencePlugin

DllReferencePlugin

在上一章节的 DllPlugin 插件中,DllPlugin 插件会将第三方依赖生成一个 [name]-dll.js 文件和一个 [name]-manifest.json 文件,其中 [name]-dll.js 文件包含第三方依赖所有的源码,[name]-manifest.json 文件包含所有第三方依赖的名称位置和与 [name]-dll.js 映射的索引 ID,执行相应命令生成了 [name]-dll.js 和 [name]-manifest.json 后,就可以执行工程的打包命令。在 webpack 打包过程中,通过 DllReferencePlugin 插件,可以将 [name]-manifest.json 文件中的第三方依赖的映射关系进行解析,当检索到有第三方依赖的映射关系时,会将三方依赖索引 ID 值注入到使用依赖的文件中。如果没有检索到三方依赖映射关系,将去 node_modules 或者项目中查找并将检索内容添加到需要使用依赖的文件中。

使用

index.js

import _ from 'lodash';
import { name } from './main.js';
console.log(_.join(['hello', 'world'], '-'))
console.log(name);

main.js

export const name = 'dll';

webpack.config.dll.js

const webpack = require('webpack');
const path = require('path');
module.exports = {
    entry: {
        vendors: ['lodash', './src/main.js'],
    },
    output: {
        filename: '[name]-dll.js',
        library: "[name]",
        path: path.resolve(__dirname, 'dist/dll')
    },
    plugins: [
        new webpack.DllPlugin({
            context: __dirname,
            path: path.join(__dirname, 'dist/dll', '[name]-manifest.json'),
            name: '[name]',
            format: true
        }),
    ]
}

在上面的配置中,将 lodash 和本地 main.js 生成 dll 文件。

webpack.config.js

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


module.exports = {
    mode: 'development',
    entry: {
        index: './src/index.js',
    },
    output: {
        path: path.resolve(__dirname, "dist"), 
        filename: '[name].js'
    },
    plugins: [
        new webpack.DllReferencePlugin({
            // 对动态链接库的文件内容的描述或者映射关系,非 dll 本身
            manifest: require('./dist/dll/vendors-manifest.json'),
        })
    ]
}

在 webpack.config.js 的 DllReferencePlugin 插件中引入 DllPlugin 插件生成的 manifest.json 文件。执行 npm run build 打包命令。我们看下生成的 index.js 文件内容。

从上面的截图我们可以看到 DllReferencePlugin 插件解析了 manifest.json 中的第三方依赖对应的映射关系,将 ID 值传入到 index.js 的方法中,我们接下来需要手动将 dll/vendors-dll.js 通过 <script> 标签添加到 index.html 中。vendors-dll.js 文件中包含第三方依赖的代码和 manifest.json 中的 ID 值,index.js 中通过加载 ID 值来使用第三方依赖方法。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Webpack App</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script defer src="./dll/vendors-dll.js"></script>
  <script defer src="index.js"></script></head>
  <body>
  </body>
</html>

在浏览器中打开 index.html 文件,在控制台可以看到输出的内容,main.js 和 lodash 方法均可正常使用。

DllReferencePlugin 在解析 manifest.json 文件时,虽然 manifest.json 包含多个第三方依赖的映射关系,但是插件会根据 index.js 中的引用来注入对应的代码。即当 index.js 中只引用了 main.js 文件时,打包后生成的 index.js 文件则只包含 main.js 的映射关系。在实际的项目中,就可以将不常改动的第三方依赖打包成 dll,将 dll 的链接通过 CDN 等方式引入到项目中,这样可以减少主包的大小,加快打包速度。

注意:[name]-dll.js 可以通过插件动态插入到 index.html,小伙伴儿可自行查阅。

配置

context

类型:String

默认值:webpack 的 context

作用:(绝对路径) manifest 中请求的上下文。

webpack.config.js

module.exports = {
  plugins: [
    new webpack.DllReferencePlugin({
      ...
      context: __dirname // 根目录地址
      // 下面的配置会在 dist 文件夹下查找 manifest 的地址,当找不到 manifest.json 文件时,会将依赖代码打包到 bundle.js 中
      // path.resolve(__dirname, "dist")
    }),
  ]
};

manifest

类型:String

作用:用于加载 manifest.json 路径。

webpack.config.js

module.exports = {
  plugins: [
    new webpack.DllReferencePlugin({
      // 动态链接库的文件内容
      manifest: require('./dist/dll/vendors-manifest.json'),
    }),
  ]
};

name

类型:String

默认值:manifest.json 的 name 属性。

作用:[name]-dll.js 暴露的全局变量方法名称,将 manifest.json 中的 索引 ID 传入全局方法中,可返回对应模块方法。

index.js

其中的 vendors(225),vendors 为 dll 暴露的全局变量,225 为 manifest.json 中 main.js 依赖的 ID 索引值。

import _ from 'lodash';
import { name } from './main.js';
console.log(_.join(['hello', 'world'], '-'))
console.log(vendors(225));
console.log(vendors(225).plugin);

main.js

export const plugin = 'dll';

webpack.config.js

module.exports = {
  ...
  plugins: [
    new webpack.DllReferencePlugin({
      ...
      name: 'vendors'
    })
  ]
};

打包成功后,控制台打开 dist/index.html,可以看到 输出了 hello-world、 main.js 模块代码和 main.js 代码中的 plugin 变量。

content

类型:Object

默认值:manifest.json 的 content 属性。

作用:传入请求依赖到模块 ID 的映射关系。

webpack.config.js

module.exports = {
  ...
  plugins: [
    new webpack.DllReferencePlugin({
      content: {
        "./src/main.js": {
          "id": 225,
          "exports": [
            "plugin"
          ]
        },
      }
    })
  ]
};

sourceType

类型:"var" | "assign" | "this" | "window" | "global" | "commonjs" | "commonjs2" | "commonjs-module" | "amd" | "amd-require" | "umd" | "umd2" | "jsonp" | "system"

作用:dll 中的模块代码以哪种模式暴露给外部调用 output.library.type

index.js

import { name } from './main.js';
console.log(window.vendors(225));

webpack.config.js

module.exports = {
  ...
  plugins: [
    new HtmlWebpackPlugin({
      ...
      sourceType: 'window'
    })
  ]
};

总结

此章节演示了 DllReferencePlugin 的用法和包含的配置参数。DllReferencePlugin 通过解析 manifest.json 将依赖的映射索引注入到需要的依赖中。通过将不常变动的依赖打包成 dll 的方式,可以减少 bundle 的大小,同时能加快打包速度。

阅读量:648

点赞量:0

收藏量:0