Ускорьте сборку проекта с помощью DllPlugin от Webpack

Webpack

В этой статье рассказывается об использовании подключаемого модуля DllPlugin в Webpack и использовании AddAssetHtmlPlugin для вставки встроенного JS-файла в HTML-страницу.

В этой статье рассматривается демонстрация

Расположение кода проекта этой статьи:Адрес источника

Добро пожаловать Звезда!


Введение в DLLPlugin и DllReferencePlugin

DLLPlugin предназначен для компиляции библиотеки, которая содержит большое количество повторно используемых модулей и редко обновляется, ее нужно скомпилировать только один раз, а после завершения компиляции она будет храниться в указанном файле (здесь можно назвать динамический библиотека ссылок). В последующем процессе сборки эти модули не будут компилироваться, а напрямую использовать DllReferencePlugin для ссылки на код библиотеки динамической компоновки. Таким образом, скорость сборки может быть значительно улучшена. Этот метод обычно используется для обычных сторонних модулей, таких как react, react-dom, lodash и т.д. Пока эти модули не обновляются, эти библиотеки динамической компоновки не нужно перекомпилировать.


Использовать с вебпаком

требуется плагин

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

Создайте файл 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>

Создайте файл index.js в каталоге src.

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'
        })
    ]
}

2. Напишите файл конфигурации для упаковки проекта (используя 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')
        })
    ]
}

3. Вставьте библиотеку динамической компоновки в файл 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.

Добавляем в 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

Откройте файл index.html в папке dist в браузере, и вы увидите, что: Здравствуйте, DllPlugin появляется в браузере. Указывает, что конфигурация проекта выполнена успешно.

Что делают DllPlugin и DllReferencePlugin соответственно

бегатьnpm run build:dllПосле инструкции видно, что в публичном каталоге проекта есть дополнительная папка 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}}}}

Это можно понять после сравнения:

  • Файл динамической библиотеки содержит код большого количества модулей, эти модули хранятся в массиве, а в качестве идентификатора используется порядковый номер массива. А еще он выставляет себя глобалу через переменную lodash_dll_lib, то есть к содержащимся в нем модулям можно получить доступ через window.lodash_dll_lib

  • Файл manifest.json четко описывает, какие модули включены в соответствующий файл dll.js, а также путь и идентификатор каждого модуля.

На этом использование и настройка Dll завершены. Но все же есть над чем подумать: в настоящее время проект может работать нормально, но теперь библиотека динамической компоновки хранится в общем каталоге.Если нам нужно упаковать проект онлайн, как можно автоматически хранить динамическую библиотеку в публичный каталог?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 в проекте, вы увидите, что файлы js в папке поставщика в общем каталоге были автоматически скопированы в папку поставщика в каталоге dist.

  • Откройте файл index.html в папке dist, вы увидите, что сгенерированный файл скрипта был автоматически импортирован.

  • Откройте index.html в браузере, вы увидите, что «Hello, DllPlugin» также может отображаться нормально.

add-asset-html-webpack-plugin Дополнительные сведения о настройке см. по адресу github:Конфигурация AddAssetHtmlPlugin


Суммировать

  • Использование динамической библиотеки Dll может повысить скорость построения проекта, так как большое количество повторно используемых модулей может быть скомпилировано заранее, и их нужно будет скомпилировать только один раз, при последующей разработке места, где используются эти модули, не будут снова перекомпилировал.

  • DllPlugin и DllReferencePlugin необходимо использовать вместе.

    • DllPlugin используется для упаковки отдельного файла библиотеки динамической компоновки и создания соответствующего основного файла манифеста, чтобы описать, какие модули включены в библиотеку динамической компоновки.
    • DllReferencePlugin используется для импорта файла библиотеки динамической компоновки, упакованного подключаемым модулем DllPlugin, в основной файл манифеста.
  • Вы можете использовать AddAssetHtmlPlugin, чтобы скопировать сгенерированный файл библиотеки динамических ссылок в папку экспорта, а затем HTMLWebpackPlugin автоматически вставит файл скрипта в сгенерированный HTML-файл.

  • **Примечание.** Чтобы проверить, увеличилась ли скорость сборки, вы можетеwebpack.config.jsАннотируйте DllReferencePlugin и AddAssetHtmlPlugin с помощью DllReferencePlugin , запуститеnpm run build, соблюдайте время упаковки, затем откройте комментарий и запуститеnpm run buildНаблюдалось время упаковки, по сравнению, различия могут быть найдены

Упаковка первого ящика, пожалуйста, запуститеnpm run build:dllСоздайте библиотеку динамических ссылок.

Демонстрационный адрес этой статьи:Адрес источника. Добро пожаловать Звезда!