金石有声,不拷不鸣
production模式打包自带优化
production模式 打包自带很多优化,例如 tree shaking、scope hoisting、代码压缩 等
tree shaking
tree shaking 指在打包时移除JS中未使用的代码(dead code),它依赖于 ES6模块化规范 的静态结构特性。
- 当引入一个模块后,只使用了模块的部分功能,打包时只会将使用到的功能打包进bundle中,其他没有使用的功能不会打包进来。
- 注意
require是动态导入,使用 CommonJS模块化规范 会影响打包时的 tree shaking 功能
scope hoisting(作用域提升)
scope hoisting 会将模块的结果进行预测,可以让webpack打包出的文件更小运行更快。
scope hoisting也是基于ES6模块化规范,它是由webpack内置插件 ModuleConcateNationPlugin实现的。
在 production模式下默认配置 ModuleConcateNationPlugin插件,其他模式默认不开启。
示例
-
新建 src/model.js
export let a = 1 export let b = 2 export let c = 9 -
main.js 对 model 模块导出的变量进行计算
import { a, b, c } from "./model.js"; const sub = (modelA, modelB, modelC) => ((modelA + modelB) * modelC) console.log("a、b、c求和结果", sub(a, b, c)); -
npm run build后查看打包结果
由上面例子可以看出 scope hoisting(作用域提升) 的强大之处,通过它webpack在打包时可以将结果推断出来,将模块打散合并为一个函数极大的避免了代码的冗余。
代码混淆、压缩
在production模式下,webpack打包时,会通过 UglifyJsPlugin 插件对代码进行混淆、压缩
css优化
css优化--css代码提取到单独文件中
前面的css代码是直接放到 html 的 style 标签中的,当相同css代码在多个模块多个页面用到时,为提高复用性避免重复编译最好还是将css代码提取到单独文件中。
对当前项目进行调整
1、优化项目目录结构
2、修改 src/webpack.base.js 配置 打包为单页面应用
module.exports = {
// 1.只指定一个入口文件
entry: "./src/main.js",
// entry: {
// index: "./src/main.js",
// other: "./src/other.js",
// },
output: {
path: path.resolve(__dirname, "..", "./dist"),
filename: '[name].js'
},
plugins: [
new HtmlPlugin(
{
filename: "index.html",
template: "./src/index.html",
// 3.也不要指定chunks 否则css可能会出现问题
// chunks: ["index", "other"]
}
),
// 2.单页面应用只生成一个html 删除生成other.html的HtmlPlugin插件
// new HtmlPlugin(
// {
// filename: "other.html",
// template: "./src/other.html",
// chunks: ["other"]
// }
// ),
]
}
3、src/main.js 导入css
import "./css/index.css"
import "./less/index.less"
MiniCssExtractPlugin
MiniCssExtractPlugin是将css提取未单独文件的插件,对每个包含css的js文件都单独生成一个css文件,支持按需加载css和sourceMap
-
安装
npm i mini-css-extract-plugin -
配置plugin和loader
// webpack.base.js // 1.导入插件构造函数 const MiniCssExtract = require("mini-css-extract-plugin") module.exports = { plugins: [ // 2.new 一个MiniCssExtract插件实例并 配置生成的css文件名 new MiniCssExtract({ filename: "main.css" }) ], module: { rules: [ { test: /\.css$/i, // 3.style-loader将css代码放入style标签中,将所有style-loader替换为MiniCssExtract的loader use: [MiniCssExtract.loader, 'css-loader'] }, { test: /\.less$/i, use: [MiniCssExtract.loader, 'css-loader', 'less-loader'] } ] } -
npm run build打包 css被单独提取出来
css优化--自动添加css属性前缀
自动添加css属性前缀是通过 postcss 实现的,使用 postcss 需要用到 postcss-loader 和 autoprefixer 插件
-
安装
npm i postcss-loader autoprefixer -
配置loader
// webpack.base.js module: { rules: [ { test: /\.css$/i, // 在css-loader右侧配置'postcss-loader' 自动添加添加css属性前缀 use: [MiniCssExtract.loader, 'css-loader', 'postcss-loader'] }, { test: /\.less$/i, // 在css-loader右侧配置'postcss-loader' 自动添加添加css属性前缀 use: [MiniCssExtract.loader, 'css-loader', 'postcss-loader', 'less-loader'] } ] } -
项目根目录新建 postcss.config.js
module.exports = { // postcss功能很单一,很多功能都依赖插件 "plugins": [ require('autoprefixer') ] } -
package.json 新增 browserslist 字段
"browserslist": [ "defaults", "not ie <= 8", "last 2 versions", "> 1%", "iOS >= 7", "Android >= 4.0" ] -
nom run build重新构建项目
css优化--css代码压缩
通过optimize-css-assets-webpack-plugin 插件完成css代码的压缩
注意:使用这个插件会出现一个问题
用生产模式打包时,webpack默认是开启js代码的压缩混淆功能的,但是如果使用 optimize-css-assets-webpack-plugin 会覆盖掉webpack默认优化配置,导致js代码无法压缩。 所以我们需要导入插件 terser-webpack-plugin 来配置一下js代码压缩功能。
-
安装
npm i optimize-css-assets-webpack-plugin terser-webpack-plugin -D -
在配置文件中添加配置节点
// webpack.prod.js // 1.导入插件 const TerserWebpackPlugin = require("terser-webpack-plugin") const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin") const prodConfig = merge(baseConfig, { // 2.添加优化配置项 optimization: { minimizer: [new TerserWebpackPlugin({}), new OptimizeCSSAssetsPlugin({})] } }) -
修改 main.js
import "./css/index.css" import "./less/index.less" let a = 20 let b = 30 function add(a, b) { return a + b } console.log("结果", add(a, b)); -
npm run build把包后js/css都成功压缩
JS代码优化
JS代码分离(Code Splitting)
Code Splitting 是 Webpack 重要特性之一,它可以将代码分离打包到不同bundle中,然后按需加载、并行加载加载这些文件。通过合理控制这些bundle资源加载的优先级,会极大影响加加载速度。例如,SPA应用单个bundle文件过大导致首屏加载速度慢的问题。
三种常见代码分离方法:
- 入口起点
手动配置多入口,通过entry配置分离代码 - 防止重复
使用SplitChunksPlugin去重和分离chunk,例如:a模块b模块都是用了jquery,我们要避免jquery被重复打包在两个模块中。 - 动态导入
通过模块内联函数调用来分离代码,例如:路由的懒加载功能
手动配置多入口
-
安装jquery
npm i jquery -
修改 src/main.js,新建 src/other.js
// main.js import $ from 'jquery' $(function () { // 新建div 插入到 body中 $("<div></div>").html("这是main.js").appendTo("body") }) // other.js import $ from 'jquery' $(function () { // 新建div 插入到 body中 $("<div></div>").html("这是other.js").appendTo("body") }) -
配置多入口
// webpack.base.js module.exports = { entry: { // 入口文件分别为 main.js / other.js main: "./src/main.js", other: "./src/other.js" } } -
npm run dev查看打包结果可以看到每个bundle只有几行代码,大小却几百kb显然是重复的JQ模块被引入到了每个bundle中
配置多入口会存在一些问题:
- 如果入口的chunks之间包含重复模块,那些重复模块会被引入到每个bundle中
- 这个种方法不够灵活,无法将程序核心的逻辑进行动态拆分
抽取公共代码
前面虽然划分了两个bundle,但是存在模块重复引入的问题。SplitChunksPlugin可以将公共的代码抽取出来。
-
修改配置文件 webpack.base.js
module.exports = { optimization: { splitChunks: { // 将所有的重复模块抽离出来 chunks: "all" } } } -
npm run build重新构建 JQ模块被单独抽离出来
动态导入
在项目开发中,一般以单页面应用程序为主很少需要配置多个入口文件,抽离公共代码也很少使用,经常使用的主要是动态导入(路由懒加载)。
CommonJS模块化 规范支持动态导入的,但是 ES6模块化 规范是静态导入。在 Webpack5 中可以通过 import(module) 实现模块动态导入
import(module)
import(module) 可以动态导入模块,它会返回一个 Promise 实例可以通过 .then 获取模块实例
-
修改src/main.js
let a = 1 if (a === 1) { console.log("a", a); import("jquery").then(({ default: $ }) => { $("<div></div>").html("这是动态导入的main.js").appendTo("body") }) } -
npm run dev查看结果
静态导入存在的问题
使用静态导入打包出的模块,在页面加载时就会全部加载进来非常影响体验
-
清空 index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <!-- <link rel="stylesheet" href="./css/index.css"> --> </head> <body> <button id="btn">插入DOM</button> </body> </html> -
修改 main.js
import $ from 'jquery' // 点击按钮后 使用JQ创建新节点并插入到页面中 document.getElementById("btn").onclick = function () { $("<div></div>").html("main.js").appendTo("body") } -
npm run server运行服务
可以看到页面加载时JQ就已经加载进来了 此时我们并未使用它
动态导入的好处
动态导入可以做到模块的按需加载(懒加载),只有当真正还是用这个模块时再去加载它
-
应用改为单入口
// webpack.base.js module.exports = { entry: "./src/main.js", // entry: { // main: "./src/main.js", // other: "./src/other.js" // } } -
修改 src/main.js
document.getElementById("btn").onclick = function () { import("jquery").then(({ default: $ }) => { $("<div></div>").html("这是动态导入的main.js").appendTo("body") }) } -
npm run dev运行服务
点击按钮之后才会加载JQ模块
代码拆分
代码拆分通过 splitChunksPlugins 插件实现的
splitChunksPlugins会根据以下默认配置自动拆分代码:
- 公共模块或者来自 node_modules 下的组件模块
- 打包的代码块大小超过30kb(最小压缩之前)
- 按需加载代码块时,同时发送请求数量不应该超过5
- 页面初始化,同时发送的请求数量不应该超过3
注意: 官网Demo示例为Mac,路径为正斜杠 window要用反斜杠取模块name!!!!
optimization: {
splitChunks: {
// 对异步加载的模块进行拆分 可选值:all(静态动态模块都拆分) | initial(对静态模块导入拆分);
chunks: 'async',
// 允许新拆出 chunk 的最小体积 20KB
minSize: 20000,
// webpack5新属性,防止0尺寸的chunk
minRemainingSize: 0,
// 模块最少引用一次才会拆分
minChunks: 1,
// 异步加载的请求数量最大不能超过30,超过5的部分不拆分
maxAsyncRequests: 30,
// 页面初始同时发送的请求数量最大不能超过30,超过30的部分不拆分
maxInitialRequests: 30,
// 当模块大小大于50KB强行进行拆分忽略其他任何限制
enforceSizeThreshold: 50000,
// 缓存组配置,上面的配置读取完成后进行模块拆分,如果多个模块拆分导一个文件上就需要缓存,所以命名为缓存组
cacheGroups: {
// 自定义 名为 commons的缓存组
commons: {
// 匹配规则
test: /[\\/]node_modules[\\/]/,
// 权重,权重越大优先级越高 当模块匹配到多个缓存组中,最终根据权重决定要打包进哪个缓存组
priority: -10,
reuseExistingChunk: true,
// 缓存组生成文件名 动态自定义
name(module, chunks, cacheGroupKey) {
console.log("模块路径", module.identifier());
const moduleFileName = module
.identifier()
// window: E:\study\basic\node_modules\jquery\dist\jquery.js
.split("\\")
// mac: E:/study/basic/node_modules/jquery/dist/jquery.js
// .split("/")
.reduceRight((item) => item);
const allChunksNames = chunks.map((item) => item.name).join('~');
// 缓存组名-[模块的依赖模块]-模块名
return `${cacheGroupKey}-${allChunksNames}-${moduleFileName}`;
},
// 缓存组生成文件名 写死自定义
filename: "vendors.js"
},
// 默认缓存组
default: {
// 模块至少引用两次才会进行拆分
minChunks: 2,
priority: -20,
// 是否复用chunk,例如 主入口有a、b两个模块,但是b模块中引用了a模块 这个打包模块时可能会出现重复打包a模块 reuseExistingChunk可以复用重复的chunk
reuseExistingChunk: true,
}
},
},
},
};
提升构建性能
打包项目时,除了对打包文件的优化,还可以提升构建性能减少构建时间。
忽略解析模块(noParse)
一些第三方模块,例如 lodash、jquery 时,可以明确知道他们并没有依赖其他模块,所以也没有必要让webpack再去解析他们模块依赖关系浪费构建性能。可以通过module.noParse 来配置不需要解析依赖关系的模块
-
src/main.js 中使用 jquery
document.getElementById("btn").onclick = function () { import("jquery").then(({ default: $ }) => { $("<div></div>").html("这是动态导入的main.js").appendTo("body") }) } -
未配置 noParse 直接打包
npm run build,构建速度约为3664毫秒 -
配置 noParse
// config/webpack.base.js module.exports = { module: { // 不对jquery模块进行解析 noParse: /jquery/, // 不对多个模块进行解析 // noParse: /jquery|lodash/ } } -
npm run build 重新构建项目
配置noParse后,构建时间减少了300多毫秒!! 在项目中配置多个noParse的模块 项目会更显著
忽略打包模块(ignorePlugin)
在引入一些第三方模块时,例如 moment ,每部会做i18n的国际化处理,会包含很多语言包。但是语言包在打包时会占用空间,如果项目只需要少数语言或某种语言,可以忽略其他语言包,这样构建项目的效率更高,打包生成的文件体积更小
ignorePlugin 可以忽略模块内部依赖的其他模块,然后我们再根据需求按需导入需要的模块
- 首先找到 moment 依赖的语言包
- 使用 ignorePlugin 忽略其依赖
- 需要使用某些依赖时自行手动引入
moment
moment 是国际化时间处理的工具库
-
安装 moment
npm i moment -
使用 moment
// src/main.js // 导入moment import moment from 'moment' // 使用中文语言包 moment.locale("zh-CN") // 六天前的日历时间 const time = moment().subtract(6, 'days').calendar(); console.log("time", time); -
npm run build查看构建结果
使用 ignorePlugin 进行优化
- 找到 moment 内部引入的语言模块
-
查看语言包位置(node_modules/moment/locale)
-
在 moment 的入口文件 搜索 require 关键字 查看内部引入的哪些模块
-
- 配置 ignorePlugin
module.exports = { plugins:[ /** * IgnorePlugin:是webpack内置插件 * IgnorePlugin(options) * - options:配置对象 * - resourceRegExp:要被忽略的模块,这里要屏蔽moment中的locale语言包模块 * - contextRegExp:使用被忽略的模块的上下文,你在哪个模块中使用了要被忽略的模块。这里语言包模块的上下文是moment模块 */ new Webpack.IgnorePlugin({ // 忽略 "./locale" 模块 resourceRegExp: /\.\/locale/, // 在moment中忽略 "./locale" 模块 contextRegExp: /moment/ }) ] } - 按需导入语言包模块
前面通过 ignorePlugin 已经忽略掉 moment.js 引入的所有语言包模块。我们需要在业务代码中按需引入语言包模块import moment from 'moment' // 手动引入中文语言包 import 'moment/locale/zh-cn' moment.locale("zh-CN") const time = moment().subtract(6, 'days').calendar(); console.log("time", time); npm run build重新打包对比之前打包之后文件大小
之前由于语言包过大 codesplit将其单独分为一个大小为228.kb的bundle。通过 ignorePlugin 处理后这个228.kb的bundle被优化掉了,同时main.js也有所减小。
谨慎使用 noParse
noParse 会忽略对模块内部依赖关系的解析,盲目使用 noParse 可能会导致模块内部依赖丢失的问题
例如 使用 ignornPlugin 忽略 moment 语言包模块依赖导入,按需导入要用的语言包后,如果将 moment 配置到 noParse 会出现bug。所以在配置 noParse 后一定要重新构建项目查看项目是否正常运行。
在对项目调优时,我们应该在每步优化后重新构建项目,查看项目是否正常运行。不要全部优化操作后再构建项目,以免出现问题后无法定位在哪步调优出现的。
生成动态链接库(DLLPlugin)
在引入一些第三方模块,例如 vue ,react , angular 等框架,这些框架模块的的代码一般不会发生变化,但是每次打包都会重新解析这些模块非常浪费性能。
可以通过 DLLPlugin 将这些模块单独打包成动态链接库,只构建一次。后面只构建业务层代码复用动态链接库,可以大大提高构建速度。
这个功能涉及两个插件
DllPlugin
使用一个单独的webpack配置文件配置DLLPlugin插件打包创建dll文件,并且还创建一个manifast.json(这个文件就是dll文件使用说明书)。DllReferenceolugin使用该json文件来做依赖映射
- context(可选):manifast文件中请求的上下文,默认为改webpack文件上下文
- name:公开的dll函数名称,要与output.library保持一致即可
- path:mainfast.json生成的路径
DllReferencePlugin
在主webpack配置文件中配置该插件,这个插件通过引用之前构建好的dll文件,自动引入之前被打包好的模块
- context:mainfast文件中请求的上下文
- mainfast:DllPlugin插件生成的mainfest.json
- content(可选):请求的映射模块id(默认为mainfest.content)
- name(可选):dll暴露的名称
- scope(可选):前缀用于访问dll的内容
- sourceType(可选):dll是如何暴露(libraryTarget)
这里结合 Vue、React 介绍下这两个插件该如何配置
Vue生成动态链接库
-
安装
npm i vue vue-router -S -
修改 index.html
<body> <div id="app">{{msg}} <div> <router-link to="/">home页面</router-link> <router-link to="/about">about页面</router-link> <router-view /> </div> </div> </body> -
初始化Vue
// src/main.js // runtime-only版 vue.js:runtime-only版无法解析template 必须配置相关loader // import Vue from 'vue' // runtime-compiler版 vue.js import Vue from 'vue/dist/vue.js' new Vue({ el: "#app", data() { return { msg: "1111" } } }) -
配置路由
// src/main.js import VueRouter from "vue-router" Vue.use(VueRouter) // 新建 Home、About组件 const Home = { template: "<h2>这是home</h2>" } const About = { template: "<h2>这是about</h2>" } // 新建路由匹配规则 const routes = [ { path: "/", component: Home }, { path: "/about", component: About } ] // 新建路由实例 const router = new VueRouter({ routes }) new Vue({ el: "#app", // 挂载路由 router, data() { return { msg: "1111" } } }) -
新建 config/webpack.vue.js
config/webpack.vue.js 是专门将Vue全家桶打包成Dll文件- 配置入口,将多个要做成dll库的模块都引入进来
- 配置出口,一定要设置library属性,将打包好的结果暴露到全局
- 配置plugin,设置打包后的dll文件名和manifest文件所在位置
// config/webpack.vue.js const path = require("path") const webpack = require("webpack") module.exports = { entry: { // vue库相关入口 vue: [ // 如果不写全 默认采用的vue.esm.js 'vue/dist/vue.js', 'vue-router' ] }, output: { path: path.resolve(__dirname, "../dist"), // 使用占位符语法 filename: "[name]_dll.js" }, plugins: [ // 通过DllPlugin 插件将模块打包成 dll文件 new webpack.DllPlugin({ // 打包后dll文件对外暴露的变量名 name: "[name]_dll", // dll文件使用说明书 path: path.resolve(__dirname, "../dist/manifest.json") }) ] }
-
新增打包dll文件的脚本
"scripts": { // 打包dll文件 "build:vue": "npx webpack --config ./config/webpack.vue.js" } -
执行
npm run build:vue得到dll文件,这Vue全家桶再也不用打包了 -
项目中使用动态链接库
前面生成了dll文件,需要在webpack配置文件中注册使用dll文件// config/webpack.base.js module.exports = { plugins: [ // 使用dll文件时,不能使用CleanWebpackPlugin插件 它会清空dll等所有dist目录 // new CleanWebpackPlugin(), // 使用dll依赖 new Webpack.DllReferencePlugin({ // 指定dll使用说明书 路径 manifest: path.resolve(__dirname, "../dist/manifest.json") }) ] }
= html引入dll模块依赖 前面我们在业务代码中注册并使用dll模块,webpack打包时默认不会加载dll模块,我们需要借助 add-asset-html-webpack-plugin 插件解决这个问题
- 安装
npm i add-asset-html-webpack-plugin -D - 配置插件
// webpack.base.js const AddAssetHtmlWebpackPlugin = require("add-asset-html-webpack-plugin") module.exports = { plugins: [ // 在打包后的html中 插入资源,这个插件一定要配置在 HtmlPlugin插件之后 new AddAssetHtmlWebpackPlugin({ // 加载dll 资源 filepath: path.resolve(__dirname, "../dist/vue_dll.js"), // 必须加这个字段 否则打包后dll引用路径前会莫名加auto publicPath: './', }) ] }-
npm run build重新打包下对比一下不使用dll的时间,由 3701ms 涨到 4731ms
-
React生成动态链接库
-
安装
npm i react react-dom -S -
修改 index.html
<body> <div id="app"></div> </body> -
新建 **main.react.js **
import React from 'react' import ReactDOM from 'react-dom' // 新建h1 虚拟DOM const node = React.createElement("h1", null, "学习好累呀,我想睡大觉!") // 通过ReactDOM 将虚拟DOM渲染到 app节点中 ReactDOM.render(node, document.getElementById("app")) -
修改入口文件、修改dll库引入路径
// config/webpack.base.js module.exports = { entry: { // 使用Vue相关库 // main: "./src/main.js", // 使用React相关库 main: "./src/main.react.js", }, plugins: [ // // 使用dll依赖 new Webpack.DllReferencePlugin({ // 指定dll使用说明书 路径 manifest: path.resolve(__dirname, "../dist/manifest.json") }), // 在打包后的html中 插入资源,这个插件一定要配置在 HtmlPlugin插件之后 new AddAssetHtmlWebpackPlugin({ // filepath: path.resolve(__dirname, "../dist/vue_dll.js"), // 加载react dll资源 filepath: path.resolve(__dirname, "../dist/react_dll.js"), // 必须加这个字段 否则打包后dll引用路径前会莫名加auto publicPath: './', }) ] } -
新建打包 react 动态链接库的 webpack 配置文件 (webpackconfig/webpack.react.js)
const path = require("path") const webpack = require("webpack") module.exports = { mode: "production", entry: { // react库相关入口 react: [ 'react', 'react-dom' ] }, output: { path: path.resolve(__dirname, "../dist"), // 使用占位符语法 filename: "[name]_dll.js", // dll库暴露出的全局变量 供业务模块使用 library: "[name]_dll" }, plugins: [ // 通过DllPlugin 插件将模块打包成 dll文件 new webpack.DllPlugin({ // 打包后dll文件对外暴露的变量名 name: "[name]_dll", // dll文件使用说明书 path: path.resolve(__dirname, "../dist/manifest.json") }) ] } -
配置打包react dll库脚本
"build:react": "npx webpack --config ./config/webpack.react.js" -
手动删除dist,执行
npm run build:react打包react dll库 -
执行
npm run build,构建整个项目
多进程打包
webpack基于node环境工作,使用单进程模式打包。在打包众多资源的情况下,可能会出现效率低下的问题,可以通过 thread-loader 实现多进程打包。
注意:进程的开启(开启大概600ms)、进程间的通讯都有时间成本,不建议小项目使用多进程打包
- 安装
npm i thread-loader -D - 配置loader
// webpack.base.js module: { rules:[ { test: /\.js$/i, exclude: /(node_modules|bower_components)/, use: [ // 使用 thread-loader "thread-loader", // { // loader: "thread-loader", // options: { // // 开启进程的数量 // workers: 2 // } // }, { loader: 'babel-loader', options: { presets: ['@babel/preset-env'], plugins: ["@babel/plugin-transform-runtime"] } } ] }, ] }
浏览器缓存
在浏览器访问页面时,会将资源缓存到硬盘或内存中,这样再次访问html中的外部资源会从本地获取,这样避免了重复从服务器请求资源极大地提高了效率。
此时会出现一个问题,就是项目开发新版本,更新业务代码上线时。由于浏览器缓存的缘故,浏览器并不会访问最新的js文件等资源,这会导致页面无法更新。
我们最好将项目代码作区分,将第三方模块和业务代码单独打包。通过构建出口 placeholder 语法,为构建输出的js文件名增加随机hash字符串。这样每次打包构建的文件名,每次访问页面也是从最新的文件访问资源。
placeholder语法变量
- name:使用元文件名
- hash:每次webpack打包随机生成哈希值
- chunkhash:不同的chunk的hash值不同,同一次打包可能生成不同的chunk
- contenthash:不同内容的hash值不同,同一个chunk中可能有不同的内容
打包分析
项目构建完成后,我们可以借助一下工具对打包完成的bundle进行分析。
通过打包结果信息json文件进行分析
-
配置script脚本指令,生成打包信息的json文件
使用--profile --json指令已json形式将打包信息输出到某个json文件中
"build:analyse": "npx webpack --profile --json > stats.json --config ./config/webpack.prod.js" -
执行
npm run build:analyse构建项目并生成构建信息文件 -
打开webpack官方分析工具上传 stats.json
链接地址:webpack.github.io/analyse/
配置分析插件进行打包分析
-
安装
npm i webpack-bundle-analyzer -D -
配置插件 (config/webpack.prod.js)
// 导入bundle分析插件 const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer") const prodConfig = merge(baseConfig, { mode: "production", plugins: [ // 初始化插件 new BundleAnalyzerPlugin() ]}) -
npm run build重新构建后,会自动运行一个分析服务