在性能优化中,我们都知道,async
属性可以让script
标签变得不阻塞HTML
解析,defer
属性也有类似的功能,但实际defer
是会阻塞script
解析的(用defer
的话,多个script
会按顺序执行,而async
执行是无序的,谁下载的快执行谁),使用async
属性理论上讲,是要比defer
更快的。
用async属性有什么问题?
感觉不太安全,因为async
会让多个script
标签执行是无序的
实际测试async,看看是否是危险的
随便用一个脚手架起项目(vue
或react
都行),build
之后,进入dist
目录下,用http-server
起服务,访问html
如下(手动改成async
)。
<!doctype html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="icon" href="/favicon.ico">
<title>hello-world</title>
<script async src="/js/chunk-vendors.f5ba3c0d.js"></script>
<script async src="/js/app.382b3f67.js"></script>
<link href="/css/app.2cf79ad6.css" rel="stylesheet">
</head>
<body>
<div id="app"></div>
</body>
</html>
用弱网访问,看下的图,很明显 app.382b3f67.js
要先下载完(因为size
小)。
确认是否是 app.382b3f67.js
先执行, 手动往2个js
里面埋入log
代码,结果和预期一样,app.382b3f67.js
先执行
确认 chunk-vendors.f5ba3c0d.js
里面的代码是关键依赖,比如是vue
或react
,理论上讲,应该是要报错的,因为依赖后执行了,但结果并没有报错。
结论
在webpack
项目内,可以放心对多个script
标签使用async
属性,webpack
已经对产物做好了兼容
webpack是如何实现兼容async的?
分析打包出来的产物,可以探知到webpack是如何实现的
产物1:app.382b3f67.js
(简化后的,方便理解)。
(function () {
"use strict";
var __webpack_modules__ = ({
4629:
(function (__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) {}),
6949:
(function (module) {})
});
!function () {
// ...
var chunkLoadingGlobal = self["webpackChunkhello_world"] = self["webpackChunkhello_world"] || [];
chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
// .push 被改写
chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
}();
var __webpack_exports__ = __webpack_require__.O(undefined, [998], function () {
return __webpack_require__(4629);
})
__webpack_exports__ = __webpack_require__.O(__webpack_exports__);
})();
console.log('app.382b3f67.js')
产物2:chunk-vendors.f5ba3c0d.js
(简化后的,方便理解)。
(self["webpackChunkhello_world"] = self["webpackChunkhello_world"] || []).push([[998], {
// ...
}]);
console.log('chunk-vendors.f5ba3c0d.js')
解释:
-
1、
app.382b3f67.js
里面的关键代码(webpack
打包时的入口代码index.js
),比如new Vue()
或root.render()
,被存放到了__webpa
ck_requir
e__(4629)
里面(每次打包数字会变,不一定是4629) -
2、4629 没有立即被执行,而是先存放好,等依赖[998]准备好,才执行
那app.382b3f67.js怎么知道依赖998已经准备好了呢?
-
1、依赖[998]就是
chunk-vendors.f5ba3c0d.js
,998被.push
到了self["webpackChunkhello_world"]
里面,这个push
不是Array.push
,而是被改写过的(我在上面写了注释,具体是哪一行被改写了) -
2、改写的作用是:可以通知到
app.382b3f67.js
,998依赖已经准备好了
由此可以得到结论:
-
依赖未准备好时,
webpack
打包时的入口代码index.js
不会执行。
-
到这里还没完,由上面的结论可以发现:如果不做特殊处理,我们几乎无法监控到
webpack
应用的白屏问题。
因为如果某个js资源网络问题丢失了,index.js
根本就不会执行,意味着上报代码也不会执行。如果js
执行报错,那直接进程退出了,上报代码也不会执行(除非try catch
了)。
学习上
作为一个软件测试的过来人,我想尽自己最大的努力,帮助每一个伙伴都能顺利找到工作。所以我整理了下面这份资源,现在免费分享给大家,有需要的小伙伴可以关注【公众号:开心螺蛳粉】自提!
软件测试面试文档
我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
文章来源:https://www.toymoban.com/news/detail-832080.html
行动吧,在路上总比一直观望的要好,未来的你肯定会感谢现在拼搏的自己!如果想学习提升找不到资料,没人答疑解惑时,请及时加入群:1150305204,里面有各种测试开发资料和技术可以一起交流哦。文章来源地址https://www.toymoban.com/news/detail-832080.html
到了这里,关于性能调优:容易忽视的JavaScript标签属性及其性能影响的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!