阅读 259

script标签有多少种属性,你知道吗?

image.png

先思考一下,问自己几个问题

  1. script标签中 integrity属性的作用是什么?
  2. crossorigin 属性如何携带凭据?
  3. defer属性的作用,defer属性加载的脚本执行顺序如何?
  4. async属性的作用,async属性加载的脚本执行顺序如何?
  5. JS动态加载脚本前,如何让浏览器预加载?

前情概要:将javaScript插入HTML中主要的方式是使用<script>元素。这个元素是由网景公司创造出来的,并最早在Netscape Navigator2中实现。后来这个元素被正式加入到HTML规范中。<script>元素有如下8个属性。

  • async: 可选。表示立即开始下载脚本,但不能阻止页面其它的动作,比如下载资源或等待其它脚本加载。只对外部脚本文件有效。在外部js文件加载完成之后,如果浏览器空闲,并且load事件触发,会在load事件触发之前执行。是异步加载,会同时并行加载多个js文件,当前文件下载完后会立即执行,不会按照书写的先后顺序
  • defer: 可选。表示脚本可以延迟到文档完全被解析和显示之后再执行。只对外部脚本文件有效。是延迟执行,会同时并行加载多个js文件,但会按照书写顺序,从上到下,依次执行。会在js加载完成之后,等到整个文档解析完成后才执行,和async执行时间不一样。
  • integrity:可选。允许比对接收到的资源和指定的加密签名以验证子资源完整性(SRI Subresource Integrity)。如果接收到的资源的签名与这个属性指定的签名不匹配,则页面会报错,脚本不会执行。这个属性可以用于确保内容分发网络(CDN)不会提供恶意内容。
  • crossorigin:可选。配置相关请求的CORS(跨源资源共享)设置。默认不使用CORS。crossorigin="anonymous"(匿名的)配置文件请求不必设置凭据标志。crossorigin="use-credentials"(凭证)设置凭据标志,意味着出站请求会包含凭据。script标签的 crossorigin 属性主要作用如下:
    • 设置 crossorigin属性后,script标签去请求资源的时候,request会带上origin头,然后会要求服务器进行 cors校验,跨域的时候如果response header 没有 ‘Access-Control-Allow-Origin’ 是不会拿到资源的。cors验证通过后,拿到的script脚本运行内部报错的话,window.onerror 捕获的时候,内部的error.message可以看到完整的错误信息。
    • crossorigin的属性值分为anonymous和use-credentials。如果设置了crossorigin属性,但是属性值不正确的话,默认是anonymous。
    • anonymous代表同域会带上cookie,跨域则不带上cookie,相当于 fecth请求的credentials: 'same-origin'。
    • use-credentials跨域也会带上cookie,相当于fetch请求的 credentials: 'include',这种情况下跨域的response header 需要设置'Access-Control-Allow-Credentials' = true,否则cors失败。
  • language:废弃。最初用于表示代码块中的脚本语言(如"JavaScript"、 "JavaScript 1.2" 或"VBScript")。大多数浏览器都会忽略这个属性,不应该再使用它。
  • src:可选。表示包含要执行的代码的外部文件。指向外部脚步文件的具体位置。
  • charset:可选。使用 src 属性指定的代码字符集。这个属性很少使用,因为大多数浏览器不 在乎它的值。
  • type:可选。代替 language,表示代码块中脚本语言的内容类型(也称 MIME 类型)。按照惯例,这个值始终都是"text/javascript",尽管"text/javascript"和"text/ecmascript" 都已经废弃了。 JavaScript 文件的 MIME 类型通常是"application/x-javascript",不过给 type属性这个值有可能导致脚本被忽略。在非IE的浏览器中有效的其他值还有"application/javascript" 和"application/ecmascript"。如果这个值是module(vite里面就用到了这个属性值),则代 码会被当成 ES6 模块,而且只有这时候代码中才能出现 import 和 export 关键字。

使用<script>的方式有两种:

  1. 通过它直接在网页中嵌入 JavaScript 代码。
<script>
    function sayHi() {
        console.log("Hi!");
    }
</script>
复制代码

包含在<script>内的代码会被从上到下解释。在上面的例子中,被解释的是一个函数定义,并且 该函数会被保存在解释器环境中。在。比如,下面的代码会导 致浏览器报错:

<script>
    function sayScript() {
        console.log("</script>");
    }
</script>
复制代码

浏览器解析行内脚本的方式决定了它在看到字符串</script>时,会将其当成结束的</script> 标签。想避免这个问题,只需要转义字符“\” 即可。 ​

  1. 通过它在网页中包含 外部 JavaScript 文件。
  • 要包含外部文件中的 JavaScript,就必须使用 src 属性。这个属性的值是一个 URL,指向包含 JavaScript 代码的文件,比如:
<script src="example.js"></script>
复制代码

与解释行内 JavaScript 一样,在解释外部 JavaScript 文件时,页面也会阻塞(阻塞时间也包含下载文件的时间)。

动态加载脚本

  • 我们可以通过JavaScript原生的DOM API,来动态添加script元素加载制定的脚本。只需要创建一个script元素并将其添加到DOM即可。
let script = document.createElement('script');
script.src = 'example.js';
document.head.appendChild(script);
复制代码

在把HTMLElement元素添加到DOM且执行到这段代码之前是不会发送请求的。默认情况下,以这种方式创建的<script>元素是以异步方式加载的,相当于添加了async属性。但这样做会存在一个问题,并不是所有浏览器都支持async属性。因此,如果要统一动态脚本的加载行为,可以明确将其设置为同步加载:

let script = document.createElement('script');
script.src = 'example.js';
script.async = false;
document.head.appendChild(script);
复制代码

但以这种方式获取的资源对浏览器预加载器是不可见的。这会严重影响它们在资源获取队列中的优先级。这样可能会对性能造成影响。要想让预加载器知道这些动态请求脚本文件的存在,可以再文档头部显示声明:

<link rel="preload" href="example.js">
复制代码

END

部分摘录于红宝书第四版,部分网上查阅资料,部分自己之前的笔记理解,更像读后感以及笔记记录,方便日后自己查阅。有不对的地方,望各位大佬多多指正。

文章分类
前端
文章标签