# 打包优化

这里使用供应链项目做优化

首先我们先安装 webpack 打包优化分析工具,这里我们推荐 webpack-bundle-analyzer

# NPM
npm install --save-dev webpack-bundle-analyzer
# Yarn
yarn add -D webpack-bundle-analyzer
1
2
3
4
首先供应链项目第一次打包的体积是 187.3 MB 共 282 个项目 js 的体积是 171.7 MB,共 164 个项目 css 的体积是 15.5 MB,共 111 个项目 打包时间6m
  1. @xmly/xm-all-address 地址数据库优化

我们搜索 js 文件夹下关键词 北京市, 发现有 35 个文件中存在, 也就是有 35 个文件中存在使用

我们先针对数据依赖库 @xmly/xm-all-address 优化

我们修改 webpack 的配置

webpackConfig.optimization.splitChunks = {
  ...webpackConfig.optimization.splitChunks,
  ...{
    chunks: "all",
    name: true,
+   cacheGroups: {
+     "xm-all-address": {
+       test: /[\\/]node_modules[\\/](\@xmly\/xm-all-address)[\\/]/,
+       name: "xm-all-address",
+       chunks: "all",
+     },
+    },
  },
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
首先供应链项目第一次打包的体积是 189.2 MB 共 284 个项目 js 的体积是 173.8 MB,共 166 个项目 css 的体积是 15.5 MB,共 111 个项目
  1. @xmly/xm-uploader 优化后
201 MB 共 284 个项目
  1. react react-dom 优化后
203.6 MB 共 289 个项目 Done in 265.39s.
{
  antd: {
    test: /[\\/]node_modules[\\/](antd|rc-tree|rc-picker)[\\/]/,
    name: 'antd',
    chunks: 'all',
  },
}
1
2
3
4
5
6
7
149.7 MB,共266个项目
{
  '@ant-design/pro-table': {
    test: /[\\/]node_modules[\\/](\@ant-design\/pro-table|\@ant-design\/pro-field)[\\/]/,
    name: 'antd',
    chunks: 'all',
  },
  jquery: {
    test: /[\\/]node_modules[\\/](jquery)[\\/]/,
    name: 'jquery',
    chunks: 'all',
  },
}
1
2
3
4
5
6
7
8
9
10
11
12
121.7 MB),共 269 个项目
{
  antd: {
    test: /[\\/]node_modules[\\/](antd|rc-).*[\\/]/,
    name: 'antd',
    chunks: 'all',
  },
  '@ant-design/pro': {
    test: /[\\/]node_modules[\\/](\@ant-design\/pro-).*[\\/]/,
    name: 'ant-design/pro',
    chunks: 'all',
  },
}
1
2
3
4
5
6
7
8
9
10
11
12
66.9 MB,共256个项目
{
  jquery: {
    test: /[\\/]node_modules[\\/](jquery|jquery\/dist)[\\/]/,
    name: 'jquery',
    chunks: 'all',
  },
  '@xmly/xm-webuploader': {
    test: /[\\/]node_modules[\\/](\@xmly\/xm-webuploader|\@xmly\/xm-webuploader\/dist)[\\/]/,
    name: 'xm-webuploader',
    chunks: 'all',
  },
}
1
2
3
4
5
6
7
8
9
10
11
12
  1. Dllplugin 优化
# 尝试:

配置路径别名,解决重复打包的问题 根据各方的查找说解决这个重复打包的问题只需要 配置一个路径别名。就会强制引入同一个路径的文件,按道理来说也是这样。

// 配置路径别名
config.resolve.alias
  .set("@", resolve("./../src"))
  .set("lib@", resolve("./../src/library"));
1
2
3
4

可是最终却怎么也不行,就算配置了路径别名还是重复打包了依赖。

可以发现他这个插件的引入方式只支持 CommonJS 引入方式,并不支持 es6 module 的引入方式。提到这个就要提提 CommonJS 跟 ES6 module 的模块化的区别了

CommonJs 和 ES6 Module 的区别

CommonJs导出的是变量的一份拷贝,ES6 Module导出的是变量的绑定(export default 是特殊的) CommonJs是单个值导出,ES6 Module可以导出多个 CommonJs是动态语法可以写在判断里,ES6 Module静态语法只能写在顶层 CommonJs的 this 是当前模块,ES6 Module的 this 是 undefined

所以可以发现 CommonJs 导出的是变量的一份拷贝。这就知道为什么我们配置了路径别名还是会重复打包了,哪里有引入他就会拷贝一份。所以哪里用到了就会打包多少份。

# 那怎么办?难道没办法了吗?

天无绝人之路,此时其实可以使用 dll 打包方式,将他打包到一个 dll.js 里面。因为 md5 这个库是不怎么变化的。而且都是公用的。

{
  // dll文件中包含的第三方库列表
  jquery: ['jquery'],
  lodash: ['lodash'],
  'react-color': ['react-color'],
}
1
2
3
4
5
6

webpack.dll.config.js

const path = require("path");
const webpack = require("webpack");
const library = "[name]_dll_lib";

module.exports = {
  mode: "development",
  // 入口, 接收多个参数作为多个入口
  entry: {
    // dll文件中包含的第三方库列表
    jquery: ["jquery"],
    lodash: ["lodash"],
    react: ["react", "react-dom", "react-color"],
  },
  output: {
    // 文件名称
    filename: "dll/[name].dll.js",
    // 文件输出目录
    path: path.resolve(__dirname, "dist"),
    // 存放dll文件的全局变量名称,需要注意命名冲突
    library: library,
  },
  plugins: [
    new webpack.DllPlugin({
      // manifest文件中的name属性值, 需与output.library保持一致
      name: library,
      // mainfest文件输出路径和文件名称
      path: path.join(__dirname, "dist", "dll/[name].manifest.json"),
    }),
  ],
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

webpack.config.js

[
  new webpack.DllReferencePlugin({
    manifest: require("./dist/dll/jquery.manifest.json"),
  }),
  new webpack.DllReferencePlugin({
    manifest: require("./dist/dll/lodash.manifest.json"),
  }),
  new webpack.DllReferencePlugin({
    manifest: require("./dist/dll/react.manifest.json"),
  }),
];
1
2
3
4
5
6
7
8
9
10
11

package.json 中添加打包命令

{
  "scripts": {
    "build:dll": "webpack --config webpack.dll.config.js",
  }
}
1
2
3
4
5

然后还需要将 dll 资源加载进 html 文件中

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

{
  // 该插件如果不能正常向html中插入文件,可能是未在html-webpack-plugin之后执行或者版本兼容问题
  // 建议看add-asset-html-webpack-plugin的最新说明
  new AddAssetHtmlPlugin({
    // dll文件位置
    glob: path.resolve(__dirname, './dist/dll/*.js'),
    // dll 引用路径
    publicPath: process.env.PUBLIC_URL + '/dll',
    // dll最终输出的目录
    outputPath: './dll',
  }),
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
  jquery: ['jquery'],
  lodash: ['lodash'],
  react: ['react', 'react-dom', 'react-color'],
}
1
2
3
4
5
49.4 MB),共263个项目
Last Updated: 3/15/2023, 2:54:57 PM