Notes

动态链接库基本配置

Demo

什么是动态链接库

Dynamic Link Library

因此,动态链接库就是那些可以随时被引用的共用模块,它们独立打包成一个模块

对于这种模块,一般应该为项目的基础设施,即项目成功运行必不可少的部分。项目依赖这种模块,而这种模块确是与项目无关。而对于一个 React 项目来说,可以为这个项目创建的动态链接库,很大可能就是 React, React-Router, React-Redux

在前端使用动态链接库的原因,除了是可以将基础设施独立打包,另外一个重要的原因是提高项目的编译构建速度,避免每次编译时都将基础设施的代码编译一次。

Webpack 中接入动态链接库

准备环境

安装依赖

假设项目中需要使用到

因此,我们需要安装如下依赖

npm i react react-dom react-router-dom redux react-redux
npm i -D webpack webpack-cli html-webpack-plugin @babel/core babel-loader @babel/preset-react @babel/preset-env webpack-dev-server

具体的配置这里省略了

配置 DLL

实际上,Webpack 内置了 DLL 的功能插件,只是一般情况下我们没有使用而已

在配置 DLL 前,我们首先要了解 Webpack 中关于 DLL 的两个插件

前者是将相关代码打包成一个动态库,而后者是将前者打包出来的库链接到 Webpack 打包过程中的业务代码,因此,后者的名字中就含有了 Reference

打包配置文件

在打包动态库的时候,Webpack 是需要一个配置文件,而这个配置文件并不是我们平时熟悉的构建配置文件,而是另一个新的文件

例如,我们新建一个打包动态库的配置文件 webpack.dll.config.js

// 动态链接库构建配置文件

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

const publichPath = path.resolve(__dirname, '..', 'public');

module.exports = {
  // 入口文件
  entry: {
    reactFamily: [
      'react',
      'react-dom',
      'react-router-dom',
      'react-redux',
    ],
  },

  // 动态链接库输出
  output: {
    filename: 'vendor.js',
    path: path.join(publichPath, 'dll'),

    // 存放动态链接库的全局变量名称,如 react -> _dll_react
    library: '_dll_[name]',
  },
  plugins: [
    new DllPlugin({
      // 与上面 output.library 中保持一致
      // 此字段是 manifest.json 中的 name 字段值
      // 如 react.manifest.json 中,name 为 "_dll_react"
      name: '_dll_[name]',

      // 对于 react, 这个就是生成 react.manifest.json 的路径
      path: path.join(publichPath, 'dll/vendor.manifest.json'),
    }),
  ],
};


Webpack 打包项目代码时,遇到动态库,将会根据 manifest.json 中的 name 进行匹配

配置链接

上面的步骤配置好了 Webpack 如何打包出动态库,接下来就需要配置动态库如何链接到项目代码中,这部分的配置就在我们熟悉的 Webpack 配置文件中进行

例如,我们的 Webpack 配置文件为 webpack.config.js

首先,我们需要引入链接动态库的文件

const webpack = require('webpack');
const DllReferencePlugin = webpack.DllReferencePlugin;

然后在 plugins 中配置规则

module.exports = {
  ...
  plugins: {
    ... // 其他插件
    
    // 动态链接库
    // 每个链接库对应一个 DllReferencePlugin 实例
    new DllReferencePlugin({
      manifest: path.join(paths.appDll, 'vendor.manifest.json'),
    }),
  },
};

动态链接库无论在开发环境还是生产环境上都可以使用,但是通过一番搜索发现,看到很多都是将动态链接库使用在开发环境上,而生产环境上,一般都是用 Webpack 自带的代码分割

打包成动态链接库,就可能会将多个依赖打包成一个库,此时动态库是无法使用代码分割的,而请求就会将整个动态库发送到客户端,因为这个动态库有可能会很大,所以造成响应的体积很大。

在 Webpack 4 中,代码分割使用了 SplitChunk, 能充分发挥按需加载的效能

如何请求动态库

由于动态库是分开的,因此,我们要在 HTML 页面中加入对动态库请求的脚本,如

<script src="./dll/vendor.js"></script>

也可以使用 html-webpack-plugin 动态配置

打包动态库

为了方便打包动态库,一般还会创建打包命令

"build:dll": "webpack --mode=production --config ./config/webpack.dll.config.js"

通过对比发现,当使用动态库时,打包出来的业务代码只有几 KB 的大小,而不使用动态库,则打包出来的业务代码有 100 多KB


当我们使用 DLL 时,执行 nom run dev