【webpack4系列】webpack构建速度和体积优化策略(五)
文章目录
- 速度分析:使用 speed-measure-webpack-plugin
- 体积分析:使用webpack-bundle-analyzer
- 使用高版本的 webpack 和 Node.js
- 多进程/多实例构建
- 资源并行解析可选方案
- 使用 HappyPack 解析资源
- 使用 thread-loader 解析资源
- 多进程并行压缩代码
- 方法一:使用 parallel-uglify-plugin 插件
- 方法二:uglifyjs-webpack-plugin 开启 parallel 参数
- 方法三:terser-webpack-plugin 开启 parallel 参数
- 进一步分包:预编译资源模块
- 分包:设置 Externals
- 进一步分包:预编译资源模块
- 充分利用缓存提升二次构建速度
- 缩小构建目标与减少文件搜索范围
- 缩小构建目标
- 减少文件搜索范围
- 使用Tree Shaking擦除无用的JavaScript和CSS
- 使用webpack进行图片压缩(压缩有问题)
- 构建体积优化:动态 Polyfill
速度分析:使用 speed-measure-webpack-plugin
使用speed-measure-webpack-plugin
插件。
官网地址:https://github.com/stephencookdev/speed-measure-webpack-plugin#readme
示例效果:
安装:
npm i speed-measure-webpack-plugin -D
使用:
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();module.exports = smp.wrap({// 其他省略plugins: [new MyPlugin(), new MyOtherPlugin()]
});
速度分析插件作用:
- 分析整个打包总耗时
- 每个插件和loader的耗时情况
体积分析:使用webpack-bundle-analyzer
示例代码:
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;module.exports = {plugins: [new BundleAnalyzerPlugin()]
}
安装:
npm i webpack-bundle-analyzer -D
可以分析哪些问题?
- 依赖的第三方模块文件大小
- 业务里面的组件代码大小
使用高版本的 webpack 和 Node.js
高版本的webpack和node.js降低了构建时间。
使用webpack4的优化原因:
- V8 带来的优化(for of 替代 forEach、Map 和 Set 替代 Object、includes 替代 indexOf)
- 默认使用更快的 md4 hash 算法
- webpacks AST 可以直接从 loader 传递给 AST,减少解析时间
- 使用字符串方法替代正则表达式
多进程/多实例构建
资源并行解析可选方案
- parallel-webpack
- HappyPack
- thread-loader
使用 HappyPack 解析资源
原理:每次 webapck 解析一个模块,HappyPack 会将它及它的依赖分配给 worker 线程中。
安装:
npm i happypack -D
使用示例:
const HappyPack = require('happypack');exports.module = {rules: [{test: /.js$/,// 1) replace your original list of loaders with "happypack/loader":// loaders: [ 'babel-loader?presets[]=es2015' ],use: 'happypack/loader',include: [ /* ... */ ],exclude: [ /* ... */ ]}]
};exports.plugins = [// 2) create the plugin:new HappyPack({// 3) re-add the loaders you replaced above in #1:loaders: [ 'babel-loader?presets[]=es2015' ]})
];
使用 thread-loader 解析资源
由于webpack4.x目前只能安装thread-loader@3.0.0
版本,3.0.0以后的版本需要webpack5.x。
原理:每次 webpack 解析一个模块,thread-loader 会将它及它的依赖分配给 worker 线程中
npm i thread-loader@3.0.0 -D
配置:
module: {rules: [{test: /.js$/,use: [{loader: "thread-loader",options: {workers: 3}},"babel-loader"]}]}
多进程并行压缩代码
方法一:使用 parallel-uglify-plugin 插件
const ParalleUglifyPlugin = require("webpack-parallel-uglify-plugin");
module.exports = {plugins: [new ParalleluglifyPlugin({uglifyjs: {output: {beautify: false,comments: false},compress: {warnings: false,drop_console: true,collapse_vars: true,reduce_vars: true}}})]
};
方法二:uglifyjs-webpack-plugin 开启 parallel 参数
建议webpack3.x使用该插件。
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
module.exports = {plugins: [new UglifyJsPlugin({uglifyoptions: {warnings: false,parse: {},compress: {},mangle: true,output: null,toplevel: false,nameCache: null,ie8: false,keep_fnames: false},parallel: true})]
};
方法三:terser-webpack-plugin 开启 parallel 参数
webpack4.x及以上建议使用terser-webpack-plugin插件
注:Using Webpack v4, you have to install terser-webpack-plugin v4.
安装:
npm i terser-webpack-plugin@4 -D
配置:
const TerserPlugin = require("terser-webpack-plugin");module.exports = {optimization: {minimizer: [new TerserPlugin({parallel: true})]}
};
进一步分包:预编译资源模块
分包:设置 Externals
思路:将 vue、react、react-dom 等基础包通过cdn 引入,不打入 bundle 中。
方法:使用html-webpack-externals-plugin
。
安装:
npm i html-webpack-externals-plugin -D
配置:
const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');module.exports = {plugins: [new HtmlWebpackExternalsPlugin({externals: [{module: "react",entry: "https://unpkg.com/react@18.2.0/umd/react.production.min.js",global: "React"},{module: "react-dom",entry: "https://unpkg.com/react-dom@18/umd/react-dom.production.min.js",global: "ReactDOM"}]})]
};
进一步分包:预编译资源模块
思路:将react、react-dom基础包和业务基础包打包成一个文件
方法:使用DLLPlugin
进行分包,DllReferencePlugin
对 manifest.json
引用
- DllPlugin:负责抽离第三方库,形成第三方动态库dll。
- DllReferencePlugin:负责引用第三方库。
使用 DLLPlugin 进行分包
新建一个webpack.dll.js:
const path = require("path");
const webpack = require("webpack");module.exports = {entry: {library: ["react", "react-dom"]},output: {filename: "[name].dll.js",path: path.join(__dirname, "build/library"),library: "[name]_[hash:8]" // 保持与webpack.DllPlugin中name一致},plugins: [new webpack.DllPlugin({name: "[name]_[hash:8]", // 保持与output.library中名称一致path: path.join(__dirname, "build/library/[name].json")})]
};
在package.json中添加命令:
"scripts": {"dll": "webpack --config webpack.dll.js"
}
最后执行npm run dll
,结果在工程根目录下有如下文件:
- build
- library.dll.js
- library.json
使用 DllReferencePlugin 引用 manifest.json
在webpack.prod.js中插件中配置如下:
plugins: [new webpack.DllReferencePlugin({manifest: require("./build/library/library.json")})
]
当执行npm run build
后其实index.html页面中没有引入library.dll.js文件,我们可以通过安装add-asset-html-webpack-plugin
插件,webpack4.x版本使用add-asset-html-webpack-plugin@3
npm i add-asset-html-webpack-plugin@3 -D
在webpack.prod.js中插件中配置如下:
plugins: [new webpack.DllReferencePlugin({manifest: require("./build/library/library.json")}),new AddAssetHtmlPlugin({filepath: path.resolve("./build/library", "library.dll.js")})
]
起作用 就是把build/library/library.dll.js拷贝到编译后的dist文件夹下,并且通过script标签引入到index.html中。
最终页面生成的效果:
<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<head><title>Document</title><link href="search_42937580.css" rel="stylesheet">
</head>
<body><div id="root"></div><script src="library.dll.js"></script><script src="search_c1f12d25.js"></script>
</body>
</html>
add-asset-html-webpack-plugin参考地址:https://www.npmjs.com/package/add-asset-html-webpack-plugin/v/3.2.2?activeTab=versions
充分利用缓存提升二次构建速度
目的:提升二次构建速度。
缓存思路:
- babel-loader 开启缓存
- terser-webpack-plugin 开启缓存
- 使用 cache-loader 或者 hard-source-webpack-plugin
开启了对应方式的缓存,会在node_modules目录下的cache文件夹看到缓存的内容,如下结构:
- node_modules
- .cache
- babel-loader
- hard-source
- terser-webpack-plugin
- .cache
1、babel-loader 开启缓存
rules: [{test: /.js$/,use: ["babel-loader?cacheDirectory=true"]}
]
如果是使用的HappyPack,配置如下:
new HappyPack({loaders: ["babel-loader?cacheDirectory=true"]
})
2、terser-webpack-plugin 开启缓存
optimization: {minimizer: [new TerserPlugin({parallel: true,cache: true})]}
3、hard-source-webpack-plugin开启缓存
安装:
npm i hard-source-webpack-plugin -D
配置:
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');module.exports = {plugins: [new HardSourceWebpackPlugin()]
}
在webpack4.x中会报错。
缩小构建目标与减少文件搜索范围
缩小构建目标
目的:尽可能的少构建模块
比如 babel-loader 不解析 node_modules
rules: [{test: /.js$/,include: [path.resolve(__dirname, "src")],use: ["babel-loader"]}
当然也可以使用exclude,来缩小构建范围。
减少文件搜索范围
- 优化 resolve.modules 配置(减少模块搜索层级)
- 优化 resolve.mainFields 配置
- 优化 resolve.extensions 配置
- 合理使用 alias
示例代码:
resolve: {alias: {"@": path.resolve(__dirname, "src"),react: path.resolve(__dirname, "./node_modules/react/umd/react.production.min.js"),"react-dom": path.resolve(__dirname, "./node_modules/react-dom/umd/react-dom.production.min.js")extensions: [".js"],mainFields: ["main"]},
使用Tree Shaking擦除无用的JavaScript和CSS
概念:1 个模块可能有多个方法,只要其中的某个方法使用到了,则整个文件都会被打到
bundle 里面去,tree shaking 就是只把用到的方法打入 bundle ,没用到的方法会在
uglify 阶段被擦除掉。
使用:webpack 默认支持,在 .babelrc 里设置 modules: false 即可
- production mode的情况下默认开启
要求:必须是 ES6 的语法,CJS 的方式不支持
无用的 CSS 如何删除掉?
- PurifyCSS: 遍历代码,识别已经用到的 CSS class
- uncss: HTML 需要通过 jsdom加载,所有的样式通过PostCSS解析,通过document.querySelector 来识别在 html 文件里面不存在的选择器
在 webpack 中如何使用 PurifyCSS?
PurifyCSS官网已经不再维护了,使用 purgecss-webpack-plugin
这个插件和 mini-css-extract-plugin
配合使用。
安装purgecss-webpack-plugin
插件:
npm i purgecss-webpack-plugin@4 -D
配置:
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const PurgeCSSPlugin = require('purgecss-webpack-plugin')const PATHS = {src: path.join(__dirname, 'src')
}module.exports = {// 其他省略module: {rules: [{test: /\.css$/,use: [MiniCssExtractPlugin.loader,"css-loader"]}]},plugins: [new MiniCssExtractPlugin({filename: "[name].css",}),new PurgeCSSPlugin({paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),}),]
}
使用webpack进行图片压缩(压缩有问题)
基于 Node 库的 imagemin
或者 tinypng API
。
使用:配置 image-webpack-loader
。
安装image-webpack-loader
:
npm i image-webpack-loader@6 -D
其中imagemin-mozjpeg
对node版本有要求:
"engines": {"node": "^12.20.0 || ^14.13.1 || >=16.0.0"}
配置:
{
test: /.(png|jpe?g|gif)$/,use: [{loader: "file-loader",options: { name: "[name]_[hash:8].[ext]" }},{loader: "image-webpack-loader",options: {mozjpeg: {progressive: true,quality: 65},// optipng.enabled: false will disable optipngoptipng: {enabled: false},pngquant: {quality: [0.65, 0.9],speed: 4},gifsicle: {interlaced: false},// the webp option will enable WEBPwebp: {quality: 75}}}]
}
Imagemin的优点分析:
- 有很多定制选项
- 可以引入更多第三方优化插件,例如pngquant
- 可以处理多种图片格式
Imagemin的压缩原理:
- pngquant: 是一款PNG压缩器,通过将图像转换为具有alpha通道(通常比24/32位PNG
- 文件小60-80%)的更高效的8位PNG格式,可显著减小文件大小。
- pngcrush:其主要目的是通过尝试不同的压缩级别和PNG过滤方法来降低PNG IDAT数据
- 流的大小。
- optipng:其设计灵感来自于pngcrush。optipng可将图像文件重新压缩为更小尺寸,而不
- 会丢失任何信息。
- tinypng:也是将24位png文件转化为更小有索引的8位图片,同时所有非必要的metadata
- 也会被剥离掉
构建体积优化:动态 Polyfill
直接把babel-polyfill打包到工程,一般会很大。
Polyfill Service原理:识别 User Agent,下发不同的 Polyfill
如何使用动态 Polyfill service?
polyfill.io 官方提供的服务
<script src="https://cdn.polyfill.io/v3/polyfill.js"></script>
相关文章:

【webpack4系列】webpack构建速度和体积优化策略(五)
文章目录 速度分析:使用 speed-measure-webpack-plugin体积分析:使用webpack-bundle-analyzer使用高版本的 webpack 和 Node.js多进程/多实例构建资源并行解析可选方案使用 HappyPack 解析资源使用 thread-loader 解析资源 多进程并行压缩代码方法一&…...
从零开始搭建 PHP
🛠️ 从零开始搭建 PHP 环境:详细教程 PHP(Hypertext Preprocessor)是最流行的后端脚本语言之一,广泛用于构建动态网站和 Web 应用程序。在开始 PHP 开发之前,首先需要搭建 PHP 运行环境。无论你使用的是 …...

【数据结构】8——图3,十字链表,邻接多重表
数据结构8——图3,十字链表,邻接多重表 文章目录 数据结构8——图3,十字链表,邻接多重表前言一、十字链表结构例子 复杂例子 二、邻接多重表(Adjacency Multilist)例子 前言 除了之前的邻接矩阵和邻接表 …...
eth-trunk 笔记
LACP:Link Aggregation Control protocol 链路聚合控制协议 将多条以太网物理链路捆绑在一起成为一条逻辑链路,从而实现增加链路带宽的目的。同时,这些捆绑在一起的链路通过相互间的动态备份,可以有效地提高链路的可靠性 一、配…...

通信工程学习:什么是接入网(AN)中的TF传送功能
接入网(AN)中的TF传送功能 在通信工程中,TF(Transfer Function)传送功能是指为接入网(AN)不同位置之间提供通道和传输介质,以实现数据的有效传输。以下是关于TF传送功能的详细解释&a…...

【JavaEE】IO基础知识及代码演示
目录 一、File 1.1 观察get系列特点差异 1.2 创建文件 1.3.1 delete()删除文件 1.3.2 deleteOnExit()删除文件 1.4 mkdir 与 mkdirs的区别 1.5 文件重命名 二、文件内容的读写----数据流 1.1 InputStream 1.1.1 使用 read() 读取文件 1.2 OutputStream 1.3 代码演示…...

安卓13系统导航方式分析以及安卓13修改默认方式为手势导航 android13修改导航方式
总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码分析4.代码修改5.彩蛋1.前言 系统导航方式默认一般是按键的,如果要改成手势的话,我们来看看用户怎么修改的: 设置=>系统=>手势=>系统导航,在这里进行修改。我们来分析下这个流程,并且将其修改为…...
[技术杂谈]暗影精灵8plus电竞版台式机安装和使用注意
最近买回二手台式机准备做深度学习训练模型使用。由于个人不是十分有钱,因此下血本入手一台,不然深度学习玩不转。配置:i9-12900K / 64G d4 3733频率 / 1TSSD2TB机械 / RTX3090 24G显卡 旗舰版 机箱45L超大机箱。买回来后整体不错&#…...
【加密算法基础——AES解密实践】
AES 解密实践 AES 解密是对使用 AES 加密算法加密的数据进行恢复的过程。 常用的解密方式有三种: 在线解密工具:格式比较好控制,但是有些在线工具兼容性不好,有时候无法解出,不知道是自己的密文密钥没找对࿰…...

Spring01
spring框架 spring是轻量级的容器框架 spring framework 1、Spring核心学习内容 IOC、AOp, jdbcTemplate,声明式事务 2、IOC:控制反转,孚以管理部8号对象 3.AOP:切面编程4.JDBCTemplate:是spring提供一套访问数据库的技术,应用性强,相对好理解5.声明式…...
gogps 利用广播星历解算卫星位置matlab函数satellite_orbits详细注解版
主要注释了广播星历计算GPS BDS卫星位置的。 function [satp, satv] satellite_orbits(t, Eph, sat, sbas)% SYNTAX: % [satp, satv] satellite_orbits(t, Eph, sat, sbas); % % INPUT: % t clock-corrected GPS time % Eph ephemeris matrix % sat satellite…...

Oracle按照某一字段值排序并显示,相同的显示序号
Oracle按照某一字段值排序并显示,相同的显示序号 最近的工作遇到对于相同的字段,按照序号去显示值,并对相同的值进行排序 实验了半天,感觉满意的答案,分享给大家 第一种: ROW_NUMBER 语法: ROW_NUMBER() OVER (ORDER BY your_column) AS sequence_number 说明: 根据your_column…...

【Java基础】String详解
文章目录 String一、String 概述1、基本特性2、不可变性3、String、StringBuilder、StringBuffer 二、字符串 创建与内存分配1、字面量 / 双引号2、new关键字3、StringBuilder.toString()4、intern() 方法5、小结 三、字符串 拼接1、常量常量2、变量 拼接3、final变量 拼接4、拼…...

cmd命令
常用命令 查看电脑名称: hostname 查看网卡信息: ipconfig 快速打开网络设置界面: control.exe netconnections 或 rundll32.exe shell32.dll,Control_RunDLL ncpa.cpld 打开防火墙设置: wf.msc 指定网卡设置IP地址&#…...

《中文Python穿云箭量化平台二次开发技术11》股票基本信息获取分析及应用示例【前十大股东占股比例提取及分析】
《中文Python穿云箭量化平台二次开发技术11》股票基本信息获取分析及应用示例【前十大股东占股比例提取及分析】 《中文Python穿云箭量化平台》是纯Python开发的量化平台,因此其中很多Python模块,我们可以自己设计新的量化工具,例如自己新的行…...
OSINT技术情报精选·2024年9月第1周
OSINT技术情报精选2024年9月第1周 2024.8.15版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 1、中国信通院:《大模型落地路线图研究报告(2024年)》 近年来,大模型技术能力不断创出新高,产业应用持续走…...

51单片机应用开发---二进制、十六进制与单片机寄存器之间的关系(跑马灯、流水灯实例)
实现目标 1、掌握二进制与十六进制之间的转换 2、掌握单片机寄存器与二进制、十六进制之间的转换 3、掌握单片机驱动跑马灯、流水灯的原理 一、二进制与十六进制之间的转换 1、二进制 二进制(binary), 是在数学和数字电路中以2为基数的…...

信息安全工程师(6)网络信息安全现状与问题
一、网络信息安全现状 威胁日益多样化:网络攻击手段不断翻新,从传统的病毒、木马、蠕虫等恶意软件,到勒索软件、钓鱼攻击、DDoS攻击、供应链攻击等,威胁形式多种多样。这些攻击不仅针对个人用户,还广泛影响企业、政府等…...

亚数TrustAsia亮相第十四届智慧城市与智能经济博览会,入围“2024数据要素创新应用优秀成果”!
智博会 2024年9月6日至8日,由宁波市人民政府、浙江省经济和信息化厅、中国信息通信研究院、中国电子信息行业联合会、中国电信、中国移动、中国联通主办的2024世界数字经济大会暨第十四届智慧城市与智能经济博览会(以下简称“智博会”)在宁波…...

Linux基础开发环境(git的使用)
1.账号注册 git 只是一个工具,要想实现便捷的代码管理,就需要借助第三方平台进行操作,当然第三平台也是基于git 开发的 github 与 gitee 代码托管平台有很多,这里我们首选 Github ,理由很简单,全球开发者…...
PostgreSQL 的扩展pg_freespacemap
PostgreSQL 的扩展pg_freespacemap pg_freespacemap 是 PostgreSQL 提供的一个内置扩展,用于查看表的空闲空间映射(Free Space Map, FSM)信息。这个扩展对于数据库性能调优和空间管理非常有用。 一 扩展概述 功能:提供对表的空…...
前端十种排序算法解析
1. 冒泡排序 1.1 说明 冒泡排序为一种常用排序算法,执行过程为从数组的第一个位置开始,相邻的进行比较,将最大的数移动到数组的最后位置执行的时间复杂度与空间复杂度为 o(n^2) 1.2 执行过程 从数组的第一个位置开始,截止位置为 …...
MySQL从入门到DBA深度学习指南
目录 引言 MySQL基础入门 数据库基础概念 MySQL安装与配置 SQL语言进阶 数据库设计与规范化 数据库设计原则 表结构设计 MySQL核心管理 用户权限管理 备份与恢复 性能优化基础 高级管理与高可用 高可用与集群 故障诊断与监控 安全与审计 DBA实战与运维 性能调…...

MySQL 索引优化(Explain执行计划) 详细讲解
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 MySQL 索引优化(Explain执行计划…...

单例模式与锁(死锁)
目录 线程安全的单例模式 什么是单例模式 单例模式的特点 饿汉实现方式和懒汉实现方式 饿汉⽅式实现单例模式 懒汉⽅式实现单例模式 懒汉⽅式实现单例模式(线程安全版本) 单例式线程池 ThreadPool.hpp threadpool.cc 运行结果 线程安全和重⼊问题 常⻅锁概念 死…...
Python 隐藏法宝:双下划线 _ _Dunder_ _
你可能不知道,Python里那些用双下划线包裹的"魔法方法"(Dunder方法),其实是提升代码质量的绝佳工具。但有趣的是,很多经验丰富的开发者对这些方法也只是一知半解。 先说句公道话: 这其实情有可原。因为在多数情况下&am…...

LLMs 系列科普文(8)
八、模型的自我认知 接下来我们聊聊另一种问题,即模型的自我认知。 网上经常经常可以看到人们会问大语言模型一些关于认知方面的问题,比如“你是什么模型?谁创造了你?” 说实话,其实这个问题有点无厘头。 之所以这么…...

AlphaDrive:通过强化学习和推理释放自动驾驶中 VLM 的力量
AlphaDrive: Unleashing the Power of VLMs in Autonomous Driving via Reinforcement Learning and Reasoning 25年3月来自华中科技大学和地平线的论文 OpenAI 的 o1 和 DeepSeek R1 在数学和科学等复杂领域达到甚至超越了人类专家水平,其中强化学习(R…...

Python读取阿里法拍网的html+解决登录cookie
效果图 import time from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from lxml import etreedef get_taobao_auct…...
数学复习笔记 27
前言 太难受了。因为一些事情。和朋友倾诉了一下,也没啥用,几年之后不知道自己再想到的时候,会怎么考虑呢。另外,笔记还是有框架一点比较好,这样比较有逻辑感受。不然太乱了。这篇笔记是关于线代第五章,特…...