Sticky Note | 重学 <script />

683 阅读2分钟

script 标签主要有三个属性

  • defer --> 立即请求文件 但不阻塞渲染引擎 等HTML解析完成之后再执行文件内容

  • async --> 立即请求文件 但不阻塞渲染引擎 文件加载完毕后阻塞渲染引擎并立即执行文件内容

  • type --> 主要是 HTML5 标准的 type = 'module' 让浏览器按照 ES6 标准将文件当作模块解析 阻塞效果默认同 defer 也可以配合 async 使用

demo

我们准备两个js文件 分别为

/**
 * @file a.js
 */
 
console.log('module A');

setTimeout(() => {
  console.log('done');
}, 2000);
/**
 * @file b.mjs
 */
console.log('module B');

const nickname = await Promise.resolve('chou');
console.log(`My name is ${nickname}`);

然后我们在html中引入这两个文件

<body>
  <script src="./a.js"></script>
  <script src="./b.mjs"></script>
  <script>
    console.log('module C');
    const h1 = document.createElement('h1');
    h1.innerText = 'Hello Script';
    document.querySelector('#container').appendChild(h1);
  </script>
  <div id="container"></div>
</body>

我们按顺序引入 a b 两个文件 然后在script底部 创建dom元素

这个时候 控制台直接报错了 原因直接通过报错信息就一目了然了

Screen Shot 2022-03-31 at 21.42.46.png

首先是 b.js 中 用到了 top-level-await 的语法 只在 ES6 module 中支持 所以

<script src="./b.mjs"></script> 要改成 <script src="./b.mjs" type="module"></script>

然后是 inline-script 里的 document.querySelector('#container').appendChild(h1) 在执行的时候未能找到id为container的dom元素 因为我们的dom元素在script后创建

所以这个script标签也要加上 type = 'module' 来延迟它的执行

这里要注意的是 deferasync 对于 inline-script 都是不会生效的 只有对于有scr属性的script标签才会生效 所以上面的场景用defer是不会生效的

改为后的 html 如下

<body>
  <script src="./a.js"></script>
  <script src="./b.mjs" type="module"></script>
  <script type="module">
    console.log('module C');
    const h1 = document.createElement('h1');
    h1.innerText = 'Hello Script';
    document.querySelector('#container').appendChild(h1);
  </script>
  <div id="container"></div>
</body>

页面信息如下

Screen Shot 2022-03-31 at 21.43.44.png

此时 如果我们将 b 模块文件 改为 async 的方式

- <script src="./b.mjs" type="module"></script>
+ <script src="./b.mjs" type="module" async></script>

此时 页面信息如下

Screen Shot 2022-03-31 at 21.45.43.png

用 mdn 上的解释

对于模块脚本,如果存在 async 属性,那么脚本及其所有依赖都会在延缓队列中执行,因此它们会被并行请求,并尽快解析和执行

总结

  1. 为了避免 script 标签 阻塞渲染引擎 应该把 script 标签放在 body 元素的最底部