关于javascript:浅析script-标签的-async-和-defer-属性

40次阅读

共计 2379 个字符,预计需要花费 6 分钟才能阅读完成。

前端当然要从 HTML 开始,咱们来聊聊在 script 标签中加上 async/defer 时的性能及差别。

都明确的情理

咱们都晓得,浏览器解析 HTML 是一行一行依照程序向后读取的,在传统的写法中,当浏览器读到 <script> 时,便会 暂停解析 DOM,同时立刻开始下载 <script> 中定义的资源,并在下载实现后立即执行。因为这样的个性,可能会造成 DOM 树在还没有齐全解析时就开始执行 JavaScript,须要操作 DOM 的程序可能因而无奈正确执行,从而造成许多问题;或是因为 <script> 中的资源下载、执行工夫过程,用户会卡在白画面,并会产生感觉网站太慢不好用之类的体验。

而解决办法也很简略,咱们须要把 <script> 标签的地位都放到 <body> 的最初一行来防止 DOM 树解析不齐全的问题,然而在简单的网站中,HTML、JavaScript 的个头都很大,须要等到整个 DOM 树都载入实现才开始下载 <script> 内的资源,从网站读取实现到可操作,会产生显著的提早感。

那这种问题该怎么解决呢?

从 HTML4 开始,<script> 多了 defer 属性,而 HTML5 则多了 async,两者都是用来帮忙开发者管制 <script> 内资源的载入及执行程序,以及防止 DOM 的解析被资源下载卡住的。

defer

defer 的意思是提早(Deferred),在 HTML4.01 标准 中规定:

设置后,这个布尔属性会向用户代理提醒该脚本将不会生成任何网页内容(例如,JavaScript 中不会生成“document.write”),因而,用户代理能够持续解析和渲染。

也就是说,在加上 defer 属性后,浏览器会持续解析、渲染画面,而不会因为须要载入<script> 内的资源而卡住;理论执行时,会在 DOMContentLoaded 执行之前,由上到下的按照摆放程序触发。

听起来很不便对吧?但要揭示各位,尽管 W3C 标准上说 defer 属性会是一个布尔值,但 IE9 以前的版本是自定义的,即便写成 <script defer="false"> 依然会有 defer 的成果,应用时要特地留神。

又是你这个老不死的 IE……

async

async 的意思是异步(Asynchronous),在 HTML5 标准 中规定:

…如果存在 async 属性,则脚本将会在可用时立刻异步执行 …

<script> 标签中加上 async 属性后,与defer 的相同点是也会在后盾执行下载,但不同的是当下载实现会马上暂停 DOM 解析(如果还没有解析实现的话),并开始执行 JavaScript。因为下载实现后会立刻执行,加上 async 属性后,就无奈保障执行程序了。

这个属性在规范中,同时也反对通过 JavaScript 动静插入 <script> 的状况。例如:

const script = document.createElement('script')
script.src = "/something/awesome.js"
document.body.append(script)

动态创建的 <script>,默认就是异步载入;但能够通过设定属性将它敞开:

script.async = false

type=”module”

在支流的古代浏览器中,<script> 的属性能够加上 type="module"。这时浏览器会认为这个文件是一个 JavaScript 模块,其中的解析规定、执行环境会略有不同;这时 <script> 的默认行为会像是 defer 一样,在后盾下载,并且期待 DOM 解析、渲染实现之后才会执行,所以 defer 属性无奈在 type="module" 的状况下产生作用。但同样能够通过 async 属性使它在下载实现后即刻执行。

用法

当初你应该明确这两个属性的特点了,那么该怎么正确地应用呢?

defer 因为后盾载入、不打断渲染及确保执行程序的特点,基本上在没非凡需要的状况下,在 <script> 中设置一下就行了;当然 <script> 自身的摆放程序还是要略微留心一下。

async 比拟特地,因为在下载后会立即执行,且不保障执行程序,个别常见的利用是设定在齐全独立的小小模块中,例如背景 Logo、页面广告等,在防止造成使用者体验变差的同时,尽量早的产生成果。

当初前端开发大都通过 Webpack 等打包工具来辅助解决,很少有本人设定这些属性的机会;开发者能够通过 script-ext-html-webpack-plugin 等插件的帮忙,将切分好的 Chunk 设定个别须要的 <script> 属性。

总结

asyncdefer<script> 专属的属性,对于网页中的其余资源,能够通过 <link>preloadprefetch 属性,来帮咱们 提早加载 将来才须要用到的资源。

尽管 <script>asyncdefer 这些属性的设置大都曾经蕴含在古代框架的打包流程中了,但只有扎实的意识这些网页最根底的标准,能力明确本人写进去的代码最初会产生什么成果。


本文首发微信公众号:前端先锋

欢送扫描二维码关注公众号,每天都给你推送陈腐的前端技术文章

欢送持续浏览本专栏其它高赞文章:

  • 深刻了解 Shadow DOM v1
  • 一步步教你用 WebVR 实现虚拟现实游戏
  • 13 个帮你进步开发效率的古代 CSS 框架
  • 疾速上手 BootstrapVue
  • JavaScript 引擎是如何工作的?从调用栈到 Promise 你须要晓得的所有
  • WebSocket 实战:在 Node 和 React 之间进行实时通信
  • 对于 Git 的 20 个面试题
  • 深刻解析 Node.js 的 console.log
  • Node.js 到底是什么?
  • 30 分钟用 Node.js 构建一个 API 服务器
  • Javascript 的对象拷贝
  • 程序员 30 岁前月薪达不到 30K,该何去何从
  • 14 个最好的 JavaScript 数据可视化库
  • 8 个给前端的顶级 VS Code 扩大插件
  • Node.js 多线程齐全指南
  • 把 HTML 转成 PDF 的 4 个计划及实现

  • 更多文章 …

正文完
 0