使用 Webpack 的 DllPlugin 提升项目构建速度

栏目: JavaScript · 发布时间: 5年前

内容简介:本文介绍了 Webpack 中 DllPlugin 插件的使用,以及配合使用 AddAssetHtmlPlugin 将构建好的 JS 文件插入到 html 页面中。本文项目代码位置:欢迎 Star!

本文介绍了 Webpack 中 DllPlugin 插件的使用,以及配合使用 AddAssetHtmlPlugin 将构建好的 JS 文件插入到 html 页面中。

本文 Demo 地址

本文项目代码位置: 源码地址

欢迎 Star!

DLLPlugin 和 DllReferencePlugin 简介

DLLPlugin 就是将包含大量复用模块且不会频繁更新的库进行编译,只需要编译一次,编译完成后存在指定的文件(这里可以称为动态链接库)中。在之后的构建过程中不会再对这些模块进行编译,而是直接使用 DllReferencePlugin 来引用动态链接库的代码。因此可以大大提高构建速度。一般会对常用的第三方模块使用这种方式,例如 react、react-dom、lodash 等等。只要这些模块不升级更新,这些动态链接库就不需要重新编译。

在 Webpack 中进行使用

需要插件

Webpack 已经内置了对动态链接库的支持,需要通过两个内置插件的配合使用。它们分别是:

  • DllPlugin 插件:用于打包出一个个单独的动态链接库文件
  • DllReferencePlugin 插件:用于在主配置文件中去引入 DllPlugin 插件打包好的动态链接库文件

创建项目

找一个空文件夹,打开命令行,执行命令

# 创建项目目录
$ mkdir webpack-dll-demo

# 初始化 package.json 文件
$ npm init -y 

# 创建 src 文件夹
$ mkdir src

# 创建 public 文件夹
$ mkdir public

# 安装需要用到的插件
$ npm install webpack webpack-cli html-webpacl-plugin clean-webpacl-plugin friendly-errors-webpack-plugin -D

# 安装 lodash 插件,用于演示 DllPlugin 用法
$ npm install lodash
复制代码

在 public 目录下创建 index.html 文件

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Webpak DllPlugin 的使用</title>
</head>
<body>
    <div id="root"></div>
</body>
</html>
复制代码

在 src 目录下创建 index.js 文件

index.js

import { join } from 'lodash';

function createSpan(){
    const element = document.createElement('span');
    element.innerHTML = join(['Hello', 'DllPlugin'], ' , ');
    return element;
}

document.querySelector('#root').appendChild(createSpan());
复制代码

当前项目目录结构

webpack-prod-demo
|- /public
  |- index.html
|- /src
  |- index.js
|- package.json
复制代码

使用 DllPlugin 和 DllReferencePlugin(分为三步)

一、先编写一个配置文件专门用来编译生成动态链接库(使用 DllPlugin)

webpack_dll.config.js

const path = require('path');
const webpack = require('webpack');
const CleanWebpaclPlugin = require('clean-webpack-plugin');
const FirendlyErrorePlugin = require('friendly-errors-webpack-plugin');

module.exports = {
    mode: 'production',
    entry: {
        // 将 lodash 模块作为入口编译成动态链接库
        lodash: ['lodash']
    },
    output: {
        // 指定生成文件所在目录
        // 由于每次打包生产环境时会清空 dist 文件夹,因此这里我将它们存放在了 public 文件夹下
        path: path.resolve(__dirname, 'public/vendor'),
        // 指定文件名
        filename: '[name].dll.js',
        // 存放动态链接库的全局变量名称,例如对应 lodash 来说就是 lodash_dll_lib
        // 这个名称需要与 DllPlugin 插件中的 name 属性值对应起来
        // 之所以在前面 _dll_lib 是为了防止全局变量冲突
        library: '[name]_dll_lib'
    },
    plugins: [
        new CleanWebpaclPlugin(['vendor'], {
            root: path.resolve(__dirname, 'public')
        }),
        new FirendlyErrorePlugin(),
        
        // 接入 DllPlugin
        new webpack.DllPlugin({
            // 描述动态链接库的 manifest.json 文件输出时的文件名称
            // 由于每次打包生产环境时会清空 dist 文件夹,因此这里我将它们存放在了 public 文件夹下
            path: path.join(__dirname, 'public', 'vendor', '[name].manifest.json'),
            // 动态链接库的全局变量名称,需要和 output.library 中保持一致
            // 该字段的值也就是输出的 manifest.json 文件 中 name 字段的值
            // 例如 lodash.manifest.json 中就有 "name": "lodash_dll_lib"
            name: '[name]_dll_lib'
        })
    ]
}
复制代码

二、编写配置文件用来打包项目(使用 DllReferencePlugin)

webpack.config.js

const path = require('path');
const webpack = require('webpack');
const HTMLWebpackPlugin = require('html-webpack-plugin');
const CleanWebpaclPlugin = require('clean-webpack-plugin');
const FirendlyErrorePlugin = require('friendly-errors-webpack-plugin');

module.exports = {
    mode: 'production',
    devtool: 'source-map',
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'build-[hash:5].js'
    },
    plugins: [
        new HTMLWebpackPlugin({
            title: 'Webpak DllPlugin 的使用',
            template: './public/index.html'
        }),
        new CleanWebpaclPlugin(['dist']),
        new FirendlyErrorePlugin(),
        new webpack.DefinePlugin({
            'process.env.NODE_ENV': JSON.stringify('production')
        }),
        // 告诉 Webpack 使用了哪些动态链接库
        new webpack.DllReferencePlugin({
            // 描述 lodash 动态链接库的文件内容
            manifest: require('./public/vendor/lodash.manifest.json')
        })
    ]
}
复制代码

三、在 index.html 文件中引入动态链接库

由于动态链接库我们一般只编译一次,之后就不用编译,复用模块都被打包到了动态链接库中,因此入口的 index.js 文件中已经不包含这些模块了,所以要在 index.html 中单独引入。

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Webpak DllPlugin 的使用</title>
</head>
<body>
    <div id="root"></div>
    <script src="../public/vendor/lodash.dll.js"></script>
</body>
</html>
复制代码

注意:由于在打包项目的时候会清理掉 dist 文件,所以我将生成的动态链接库放到了 public 目录下,所以这里是引入 public 下的动态链接库。

我们在 package.json 中添加两条指令:

  • build:打包项目
  • build:dll:编译生成动态链接库

package.json

...
"scripts": {
    "build": "webpack --config webpack.config.js",
    "build:dll": "webpack --config webpack_dll.config.js"
}
...
复制代码

运行

根据上面所说的三个步骤,Dll 的用法已经结束了。现在我们运行一下看看结果。

打开命令行,执行命令

# 生成动态链接库,只需要运行一次这个指令,以后打包项目不需要再执行这个指令
$ npm run build:dll

# 打包项目
$ npm run build
复制代码

在浏览器中打开 dist 文件夹下的 index.html 文件,可以看到浏览器上出现:Hello , DllPlugin。说明项目配置成功。

DllPlugin 和 DllReferencePlugin 分别做了什么

运行 npm run build:dll 指令之后,可以看到项目中 public 目录下多出了一个 vendor 的文件夹,可以看到其中包含两个文件:

  • lodash.dll.js 里面包含 lodash 的基础运行环境,也就是 lodash 模块
  • lodash.manifest.json 也是由 DllPlugin 生成出,用于描述动态链接库文件中包含哪些模块

lodash.dll.js

var lodash_dll_lib=...  // 此处代码过多,进行省略
复制代码

lodash.manifest.json

{"name":"lodash_dll_lib","content":{"./node_modules/lodash/lodash.js":{"id":1,"buildMeta":{"providedExports":true}},"./node_modules/webpack/buildin/global.js":{"id":2,"buildMeta":{"providedExports":true}},"./node_modules/webpack/buildin/module.js":{"id":3,"buildMeta":{"providedExports":true}}}}
复制代码

对比之后可以明白:

  • 一个动态链接库文件中包含了大量模块的代码,这些模块存放在一个数组里,用数组的索引号作为 ID。 并且还通过 lodash_dll_lib 变量把自己暴露在了全局中,也就是可以通过 window.lodash_dll_lib 可以访问到它里面包含的模块

  • manifest.json 文件清楚地描述了与其对应的 dll.js 文件中包含了哪些模块,以及每个模块的路径和 ID

至此,Dll 的使用以及配置完成了。但是这里还有值得思考的地方:目前看来,项目可以正常运行,但是现在动态链接库是存放到 public 目录下的,如果我们需要将项目打包上线的话,如何能够让动态链接库自动也存放到 dist 目录下呢?如何在我们不手动添加脚本的情况下,自动将动态链接库引入到 index.html 文件中呢?如果有兴趣的话,可以继续往下来看一看配合 add-asset-html-webpack-plugin 的使用。

add-asset-html-webpack-plugin 的使用

上面也已经说了,虽然 Dll 的使用和配置没有问题了,但是还不是很满意,打包的时候不能将动态链接库自动的存放到 dist 文件夹,也不能自动在 html 文件中引入动态链接库脚本。所以这时候 add-asset-html-webpack-plugin 就派上用场了。

安装插件

$ npm install add-asset-html-webpack-plugin -D
复制代码

使用

在 webpack.config.js 文件中进行使用

webpack.config.js

...;
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');

module.exports = {
    ...,
    plugins: [
        ...,
        // 该插件将把给定的 JS 或 CSS 文件添加到 webpack 配置的文件中,并将其放入资源列表 html webpack插件注入到生成的 html 中。
        new AddAssetHtmlPlugin([
            {
                // 要添加到编译中的文件的绝对路径,以及生成的HTML文件。支持globby字符串
                filepath: require.resolve(path.resolve(__dirname, 'public/vendor/lodash.dll.js')),
                // 文件输出目录
                outputPath: 'vendor',
                // 脚本或链接标记的公共路径
                publicPath: 'vendor'
            }
        ])
    ]
}
复制代码

此时可以删除 index.html 文件中手动引入的脚本了

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Webpak DllPlugin 的使用</title>
</head>
<body>
    <div id="root"></div>
    <!-- 删除下面这行引入脚本 -->
-    <script src="../public/vendor/lodash.dll.js"></script>
</body>
</html>
复制代码

运行项目

打开命令行,执行命令:

# 打包项目
$ npm run build
复制代码
  • 现在查看项目中 dist 文件夹,可以看到 public 目录下 vendor 文件夹中的 js 文件已经全部自动拷贝到 dist 目录中的 vendor 文件夹下了

  • 打开 dist 文件夹中的 index.html 文件,可以看到已经自动将生成的脚本文件引入了

  • 在浏览器中打开 index.html,可以看到 'Hello , DllPlugin' 也能够正常显示

add-asset-html-webpack-plugin 更多配置请参考 github 地址: AddAssetHtmlPlugin 配置


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

零基础学PHP

零基础学PHP

马忠超 / 2008-3 / 56.00元

《零基础学PHP》主要内容:PHP是一种运行于服务器端并完全跨平台的嵌入式脚本编程语言,是目前开发各类Web应用的主流语言之一。PHP因其功能强大、易学易用、可扩展性强、运行速度快和良好的开放性,而成为网站开发者的首选工具,其较高的开发效率,也给开发人员在编写Web应用程序时带来极大的便利。一起来看看 《零基础学PHP》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

html转js在线工具
html转js在线工具

html转js在线工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换