webpack性能优化

2023-11-06

性能优化介绍

  • 开发环境性能优化
  • 生产环境性能优化

开发环境性能优化

  • 优化打包构建速度
  • 优化代码调试

生产环境性能优化

  • 优化打包构建速度(与开发环境的优化角度不一样)
  • 优化代码运行的性能

开发环境性能优化

HMR(hot module replacement)

HMR 被称为 模块热替换/热模块替换。
作用:一个模块发生变化,只会重新打包这一个模块(而不是打包所有模块),极大提升构建速度
使用:在 devServer 中配置如下

devServer:{
	contentBase:resolve(__dirname,'build'),
	compress:true,
	port:3000,
	open:true,
	// 开启 HMR 功能
	// 当修改了 webpack 配置,必须重新执行 npx webpack-dev-server
	hot:true
}

文件分为以下三种文件:
样式文件:可以使用 HMR 功能,因为 style-loader 内部实现了
JS文件:默认不能使用 HMR 功能 —> 需要修改JS代码,添加支持 HMR 功能的代码
注意:HMR 功能对JS的处理,只能处理非入口JS文件的其他文件
HTML文件:默认不能使用 HMR 功能,同时会导致问题:HTML 文件不能热更新了(不用做 HMR 功能,因为 HTML 文件只有一个,一旦改变,只有它自己变)
解决:修改 entry 入口,将 HTML 文件引入

JS文件添加支持 HMR 功能的代码如下:
只能在入口JS文件中添加,假设文件名叫 print.js

import print from './print.js'

if(module.hot){
	// 一旦 module.hot 为 true,说明开启了 HMR 功能。 ---> 让 HMR 功能代码生效
	module.hot.accept('./print.js',()=>{
		// 方法会监听 print.js 文件的变化,一旦发生变化,其他模块不会重新打包构建。
		// 会执行后面的回调函数
		print()
	})
}

开发环境下调试代码(source-map)

source-map:一种提供源代码到构建后代码映射技术(如果构建后代码出错了,通过映射可以追踪源代码错误)。
它在index.js中声明一下就可以了,如下:

devtool:'source-map'

它会有一些参数:
source-map:外部
错误代码准确信息和源代码的错误位置

inline-source-map:内联
只生成一个内联source-map

hidden-source-map:外部
错误代码错误原因,但是没有错误位置。不能追踪源代码错误,只能提示到构建后代码的错误位置

eval-source-map:内联
每一个文件都生产对应的source-map,都在eval
错误代码准确信息和源代码的错误位置

nosources-source-map:外部
错误代码准确信息,但是没有任何源代码信息

cheap-source-map:外部
错误代码准确信息和源代码的错误位置
只能精确到行

cheap-module-source-map:外部
错误代码准确信息,但是没有任何源代码信息
module会将loader的source-map加入

内联和外部的区别:1.外部生产了文件,内联没有
2.内联构建速度更快

使用场景:
开发环境:速度快,调试更友好
速度快(eval>inline>cheap>…)
eval-cheap-source-map
eval-source-map
调试更友好
source-map
cheap-module-source-map
cheap-source-map

vue 和 react脚手架默认使用的 eval-source-map

生产环境:源代码要不要隐藏?调试要不要更友好?
内联会让代码体积变大,所以在生产环境不用内联
nosources-source-map 全部隐藏
hidden-source-map 只隐藏源代码,会提示构建后代码错误信息

	一般使用 source-map /  cheap-module-source-map

oneOf

oneOf 中的 loader 只会匹配一个,提高 loader 的处理性能
注意:不能有两个配置处理同一种类型的文件
使用方法:

module.exports = {
	rules:[
		{
			oneOf:[
				// 这里面配置loader,不能有2个loader处理同一种文件
			]
		}
	]
}

缓存

  1. babel 缓存
    让第二次打包构建速度更快
    在配置 babel-loader 的配置选项中添加如下配置就行:
// 开启 babel 缓存
// 第二次构建时,会读取之前的缓存
cacheDirectory:true
  1. 文件资源缓存
    让代码上线运行缓存更好使用
    hash:每次 webpack 构建时会生成一个唯一的 hash 值。
    问题:因为js和css同时使用一个hash值,如果重新打包,会导致所有缓存失效。(可能我只改动了一个文件)
    解决:chunkhash 根据chunk生产的hash值。如果打包来源于同一个chunk,那么hash值就一样。
    问题:js和css的hash值还是一样的,因为css是在js中被引入的,所以同属于一个chunk。
    解决:contentchunk 根据文件的内容生成hash值。不同文件hash值一定不一样

    使用方法:在文件名里加hash值

// 如这样使用:
filename:'css/built.[contenthash:10].css',

tree shaking(去除无用代码)

前提:1.必须使用ES6模块化 2.开启 production 环境
作用:减少代码体积

在package.json中配置

"sideEffects": false  // 所有代码都没有副作用(都可以进行tree shaking)
// 问题:可能会把 css/ @babel / polyfill (副作用)文件干掉
// 解决:
"sideEffects":["*.css"]

code split(代码分割)

单页面一般配置单入口
多页面一般配置多入口
第一种配置:

// 单入口
entry:'./src/js/index.js'

// 多入口:有一个入口,最终输出就有一个 bundle
entry:{
	index:'./src/js/index.js',
	test:'./src/js/test.js'
}

output:{
	// [name]:取文件名
	filename:'js/[name].[contenthash:10].js'
}

第二种:
多入口优化设置,在 webpack.config.js 中配置:

// 1.可以将 node_modules 中代码单独打包一个chunk最终输出
// 2.自动分析多入口 chunk 中,有没有公共的文件。如果有会打包成单独一个chunk
optimization:{
	splitChunks:{
		chunks:'all'
	}
}

第三种:常用于单页面,并行加载,加载速度更快
通过js代码,让某个文件被单独打包成一个chunk

// import 动态导入语法:能将某个文件单独打包
import(/* webpackChunkName:'test' */'./test').then((result)=>{
	console.log(result)
}).catch(()=>{
	console.log('文件加载失败~')
})

懒加载和预加载

懒加载:当文件需要使用时才加载~
例:

// 在HTML文件中添加一个按钮
<button id="btn">点我</button>

// 在index.js入口文件中设置如下代码实现懒加载:
document.getElementById('btn').onclick = function(){
	import('./test').then((result)=>{
		console.log(result)
	})
}

只有当点击按钮时才加载 test.js 文件,实现了文件的懒加载

预加载 prefetch:会在使用前,提前加载js文件,兼容性较差
正常加载可以认为是并行加载(同一时间加载多个文件),预加载是等其他资源加载完毕,浏览器空闲了,再偷偷加载资源
实现代码如下:

// 在HTML文件中添加一个按钮
<button id="btn">点我</button>

// 在index.js入口文件中设置如下代码实现预加载:webpackPrefetch:true
document.getElementById('btn').onclick = function(){
	import(/* webpackChunkName:'test',webpackPrefetch:true */'./test').then((result)=>{
		console.log(result)
	})
}

PWA(渐进式网络开发应用程序:离线可访问)

需要用到 workbox 这个插件,先下载

npm i workbox-webpack-plugin

// 引入
const WorkboxWebpackPlugin = require('workbox-webpack-plugin')

使用:在 plugins 数组中直接配置

/*
	1.帮助 serviceworker 快速启动
	2.删除旧的 serviceworker

	生产一个 serviceworker 配置文件~
*/
new WorkboxWebpackPlugin.GenerateSW({
	clientsClaim:true,
	skipWaiting:true
})

在入口文件 index.js 中注册 serviceworker,还要处理兼容性问题

/* 
	1.eslint 不认识 window、navigator 等全局变量
		解决:需要修改 package.json 中eslintConfig 配置
		"env":{
			"browser":true //支持浏览器端全局变量	
		}

	2.serviceworker 代码必须运行在服务器上
	----> nodejs
	----> npm i serve -g , serve -s build 启动服务器,将 build 目录下所有资源作为静态资源暴露出去
*/

if('serviceWorker' in navigator){
	window.addEventListener('load',()=>{
		navigator.serviceWorker.register('./service-worker.js').then(()=>{
			console.log('sw注册成功~')
		}).catch(()=>{
			console.log('sw注册失败了~')
		})
	})
}

多进程打包

使用 thread-loader 开启多进程打包。
进程启动大概为 600ms,进程通信也有开销,只有工作消耗时间比较长,才需要多进程打包,开启需要如下配置:

{
	loader:'thread-loader',
	options:{
		workers:2  // 2个进程
	}
}

externals

在 webpack.config.js 中配置

externals:{
	// 拒绝jQuery被打包进来
	jquery:'jQuery'
}

作用:能用cdn在HTML文件中引入的,可以配置一下externals,可以提高打包速度。

dll

将库文件提前打包好,然后引入,
与externals不同在于,externals直接不打包
缺点是配置比较多

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

webpack性能优化 的相关文章

  • 主干视图 DOM 元素已删除

    我一直在阅读有关 Backbone js 僵尸 或内存泄漏 问题的信息 基本上 当您不再需要该元素时 您必须从 DOM 中解除绑定并删除该元素 以确保所有事件也被删除 现在 我有一个包含几个容器的单页应用程序 div div div div
  • 如何测试 javascript 闭包内的函数

    这似乎是不可能的 也可能是 但我正在尝试更多的 TDD 但我总是在闭包方面碰壁 假设我有以下内容 function createSomething init function privateMethod param return init
  • React js Stripe 结账不起作用

    我正在尝试在 React js 应用程序中呈现条带结账默认表单
  • 不和谐机器人 |不和谐.js |类型错误:无法读取未定义的属性“长度”

    我正在制作一个 Discord 机器人 并且正在使用 CodeLyon 的视频作为参考 该错误位于我的 message js 文件中 该文件包含以下内容 require dotenv config create cooldowns map
  • 为什么 JavaScript base-36 转换看起来不明确

    我目前正在编写一段使用 Base 36 编码的 JavaScript 我遇到了这个问题 parseInt welcomeback 36 toString 36 看来要回归了 welcomebacg 我在 Chrome 开发者控制台和 Nod
  • jquery.find() 可以只选择直接子项吗?

    我应该向 jQuery find 提供什么参数来选择元素子元素而不选择其他元素 我不能用 gt 引导选择器 而用 将选择所有后代 而不仅仅是直接子代 我知道 jQuery children 但这是一个库 因此用户能够提供自己的选择器 并且我
  • 使用 useReducers 调度函数发送多个操作?

    使用时是否可以通过调度函数发送多个动作useReducer挂钩反应 我尝试向它传递一组操作 但这会引发未处理的运行时异常 明确地说 通常会有一个初始状态对象和一个减速器 如下所示 const initialState message1 nu
  • 如何防止 Iframe 在与浏览器交互后弄乱浏览器的历史记录?

    因此 就我而言 我使用 Iframe 将 Grafana 附加到我的页面 这为我提供了漂亮且易于使用的图表 可以注意到 每次在图表上进行放大或缩小 使用鼠标单击 交互后 Grafana 的 Iframe 都会在我的 Angular 页面上触
  • 如何抑制窗口鼠标滚轮滚动...?

    我正在开发嵌入页面中的画布应用程序 我有它 因此您可以使用鼠标滚轮放大绘图 但不幸的是 这会滚动页面 因为它是文章的一部分 当我在 dom 元素上滚动鼠标滚轮时 是否可以阻止鼠标滚轮在窗口上滚动 附加鼠标滚轮 不是 Gecko DOMMou
  • 跟踪用户何时点击浏览器上的后退按钮

    是否可以检测用户何时单击浏览器的后退按钮 我有一个 Ajax 应用程序 如果我可以检测到用户何时单击后退按钮 我可以显示适当的数据 任何使用 PHP JavaScript 的解决方案都是优选的 任何语言的解决方案都可以 只需要我可以翻译成
  • 在javascript中解析json - 长数字被四舍五入

    我需要解析一个包含长数字的 json 在 java servlet 中生成 问题是长数字被四舍五入 当执行这段代码时 var s x 6855337641038665531 var obj JSON parse s alert obj x
  • Babel 7 Jest Core JS“TypeError:wks不是函数”

    将我的项目升级到 Babel 7 后 通过 Jest 运行测试会抛出以下错误 测试在 Babel 6 中运行没有任何问题 但在 Babel 7 中失败并出现以下错误 TypeError wks is not a function at Ob
  • 如何使用tampermonkey模拟react应用程序中的点击?

    我正在尝试使用 Tampermonkey 脚本模拟对 React 元素的点击 不幸的是 由于 React 有自己的影子 DOM 所以天真的方法使用document querySelector 不工作 我遇到了一些需要修改 React 组件本
  • 为什么我不能在 AngularJS 中使用 data-* 作为指令的属性名称?

    On the t他的笨蛋 http plnkr co edit l3KoY3 p preview您可以注意到属性名称模式的奇怪行为data 在指令中 电话 Test of data named attribute br
  • 在 vue.js 中访问数组对象属性

    给定以下数组vue js packageMaps Object packageMap 0 Object Id 16 PackageType flag list ProductCode F BannerBase packageMap 1 Ob
  • 条件在反应本机生产中失败,但在开发中有效

    我创建了一个反应本机应用程序 我需要通过它进行比较 如果属实 就会执行死刑 问题是 该条件适用于 React Native 开发模式 而不适用于 React Native 生产版本 我使用 firebase 作为数据库 也使用 redux
  • Javascript 纪元时间(以天为单位)

    我需要以天为单位的纪元时间 迄今为止 我已经看到过有关如何翻译它的帖子 但几天后就没有了 我对纪元时间很不好 我怎么能得到这个 我需要以天为单位的纪元时间 我将解释为您想要自纪元以来的天数 纪元本身是第 0 天 或第 1 天的开始 无论您如
  • 如何更改此 jquery 插件的时区/时间戳?

    我正在使用这个名为 timeago 的插件 在这里找到 timeago yarp com 它工作得很好 只是它在似乎不同的时区运行 我住在美国东部 费城时区 当我将准确的 EST 时间放入 timeago 插件时 比如 2011 05 28
  • 将 MQTTNet 服务器与 MQTT.js 客户端结合使用

    我已经启动了一个 MQTT 服务器 就像this https github com chkr1011 MQTTnet tree master例子 该代码托管在 ASP Net Core 2 0 应用程序中 但我尝试过控制台应用程序 但没有成
  • fullCalendar 未显示正确的结束日期

    我正在看调试页面 http jsbin com wukofacaxu edit js outputFullCalendar 官方网站的 我想安排一个活动时间为 22 09 2015 至 30 09 2015 dd mm yyyy 但它只显示

随机推荐

  • 【转载】做好功能测试,这8项必备技能了解一下!

    原文链接 功能测试是测试工程师的基础功 很多人功能测试还做不好 就想去做性能测试 自动化测试 很多人对功能测试的理解就是点点点 如何自己不用心去悟 去研究 那么你的职业生涯也就停留在点点点上了 在这里 我把我对功能测试的理解写下来 那么 功
  • Can not load Open Client,please verify that libct.dll and libcs.dll are in your

    Can not load Open Client please verify that libct dll and libcs dll are in your path Please make sure your version of Op
  • C++ 函数模板与类模板template,以及具体化、实例化

    函数模板 需要创建针对不同参数类型的实现相同功能的不同函数 注 模板不能缩短可执行程序 最终仍是有多个独立的函数定义 另 若对不同类型的参数执行不同的算法 可以重载模板定义 前提是两函数的特征标不同 例 template
  • arduino+oled显示字

    OLED 显示屏有四个引脚 分别是 SDA 数据线 SCK 时钟线 VDD 3 3V GND 在UNO开发板上I2C接口 SDA对应D4 SCK对应D5 在MEGA2560开发板上I2C接口 SDA对应D20 SCL对应D21 首先下载一个
  • 随笔 笔记

    一 ES6数组去重结果 new set array 二 cmd 管理员身份运行 ipconfig flushdns 刷新dns 有时某个网站进不去就刷新一下 比如echarts中文官网 三 检查元素中 快速搜索文件所在位置 浏览器打开 f1
  • 顶尖程序员不同于常人的 5 个区别

    2019独角兽企业重金招聘Python工程师标准 gt gt gt The Effective Engineer 的作者在写书的过程中 为了了解那些顶级程序员和普通程序员的区别 采访了很多硅谷顶级科技公司的顶尖软件工程师 他发现这些给世界带
  • Rust 移动零

    给定一个数组 nums 编写一个函数将所有 0 移动到数组的末尾 同时保持非零元素的相对顺序 请注意 必须在不复制数组的情况下原地对数组进行操作 力扣https leetcode cn problems move zeroes Rust代码
  • Java事件处理和事件派发机制

    事件处理 GUI程序是事件驱动程序 因此我们需要学习Java的事件处理 常见的事件包括 移动鼠标 单双击鼠标各个按钮 单击按钮 在文本字段输入 Swing通过事件对象来包装事件 程序可以通过事件获取事件的有关信息 事件处理的几个要素 事件源
  • python中16mod7_Python小白学习之路(十六)—【内置函数一】

    将68个内置函数按照其功能分为了10类 分别是 数学运算 7个 abs divmod max min pow round sum 类型转换 24个 bool int float complex str bytearray bytes mem
  • 现代C++之SFINAE应用(小工具编写)

    现代C 之SFINAE应用 小工具编写 0 导语 现在考虑这个输入 map
  • 【计算机毕业设计】-java家教系统视频教程-手把手教你制作

    很多大四同学苦于没有参考的毕设资料 或者下载的资料不全 代码有问题 数据有问题等等 造成毕设出现问题影响大学毕业 现在 免费提供项目源码和视频教程 让大家在短时间内可以完成自己的毕业设计 对于java方向的毕业设计题目选题 我们可以从技术点
  • java javax.mail包报错550 Mailbox not found or access denied

    java javax mail包报错550 Mailbox not found or access denied 报错信息如下所示 拦截异常信息 获取发送失败的邮箱地址 进行打印 未发送成功的邮箱地址进行重发 或者可以直接将无效的邮箱从数据
  • 输入2 个字符串S1 和S2,要求删除字符串S1 中出现的所有子串S2

    输入2 个字符串S1 和S2 要求删除字符串S1 中出现的所有子串S2 题目内容 输入2 个字符串S1 和S2 要求删除字符串S1 中出现的所有子串S2 即结果字符串中不能包含S2 提示 输入数据的设计使得不可能出现输出为空的情况 输入格式
  • 在本地wz-dev分支拉取远程dev总分支最新代码的流程

    文章目录 0 图片说明 1 在wz dev分支上进行git add 和git commit m 2 切换到dev分支 拉取代码 与本地wz dev代码进行合并 推送合并后的代码到远程dev分支 3 切换到wz dev分支 与dev分支合并
  • FastAPI从入门到实战(2)——Pydantic模型

    前面了解了一下python的类型提示 这里就接着记录一下Pydantic这个用来执行数据校验的库 而且FastAPI就是基于python的类型提示和Padantic实现的数据验证 简介 官网 https pydantic docs help
  • python anova_使用Python进行双向ANOVA的三种方法

    python anova In an earlier post I showed four different techniques that enables two way analysis of variance ANOVA using
  • VS2010调试-显示堆栈窗口

    以中断模式或运行模式显示 调用堆栈 窗口 在 调试 菜单中选择 窗口 然后单击 调用堆栈 或者 ALT 7 更改显示的可选信息 右击 调用堆栈 窗口 然后设置或清除 显示 lt 所需信息 gt 在 调用堆栈 窗口中显示非用户代码帧 右击 调
  • javascript Date format(js日期格式化)

    javascript Date format js日期格式化 方法一 对Date的扩展 将 Date 转化为指定格式的String 月 M 日 d 小时 h 分 m 秒 s 季度 q 可以用 1 2 个占位符 年 y 可以用 1 4 个占位
  • SAP 资产屏幕增强(AS01/AS02/AS03)

    导语 最新需要在资产屏幕上增加增强字段 效果图在最后 下面分享一下实现过程 一 在表中增强字段 本次增强的是 资产主数据 gt 源 中的字段 选择储存在ANLU表中 二 创建屏幕 在函数组XAIS中创建屏幕9001 在屏幕上绘制需要增强的字
  • webpack性能优化

    webpack性能优化 性能优化介绍 开发环境性能优化 生产环境性能优化 开发环境性能优化 HMR hot module replacement 开发环境下调试代码 source map oneOf 缓存 tree shaking 去除无用