偷窥脚本标签0x01什么是脚本标签?脚本标签允许您将一些动态脚本或数据块包含到文档中。脚本标签不闭合,也可以使用动态脚本或数据块作为脚本文本节点。那是内联脚本。一般我们最常用的就是在script标签里面写一些JavaScript脚本,但是脚本也可以用来存储一些数据,比如当你设置type="text/react"的脚本时,你可以把react代码放在里面,但是浏览器不能识别的type是不会执行的,所以也可以用script来存放一些临时的APP数据。也有效第一个脚本的内容通过documents.scripts[0].text,可以修改,但不会有任何影响。0x02src属性当指定src属性时,外部脚本的内容不受脚本内容的限制;同时,您的脚本标签必须为空。如果没有指定src,则称该脚本是内联的,内联脚本受脚本内容的限制。什么是脚本内容限制?所以可以看到,如果为了降低CRP而使用打包工具将脚本内联到文档中,代码要注意是否满足脚本内容限制;如果你也压缩了代码,你需要多注意这一点。0x03defer和async属性0x04脚本中有type=module和nomodule属性,默认type="text/javascript"也可以是JavaScriptMIME中的任意一种。如果脚本是用JavaScript编写的,建议省略type属性。不指定defer和async执行经典脚本会阻塞DOM解析。如果type=module,则表示该标签引用的是一个ES模块。//utils.jsexport函数addTextToBody(text){constdiv=document.createElement('div');div.textContent=文本;document.body.appendChild(div);}只支持“裸导入”//Supported:import{foo}from'https://jakearchibald.com/utils/bar.js';import{foo}from'/utils/bar.js';import{foo}from'./bar.js';import{foo}from'../bar.js';//不支持:import{foo}from'bar.js';import{foo}来自'utils/bar.js';支持type=module的浏览器会自动忽略带有nomodule的脚本标签。方便您退回到不支持模块的旧式用户代理。andtype=moduledefaultstodefer执行顺序是2.js,1.js,3.js即使是内联模块,它还是有defer属性的。模块脚本只会执行一次必须符合同源策略跨域时模块脚本默认没有凭据下图可以很好的说明经典脚本和模块脚本加载的不同模块脚本的依赖级别增加是否会导致增加在CRP增加的长度?从上图可以看出,当层级很深时,UserAgent会花费大量时间等待依赖文件的传输和解析,所以这会导致CRP的长度增加;然而,http2push的魔力使得用户代理下载依赖文件。时间会大大减少,服务端会分析模块的依赖树,然后在一个请求中将所有的依赖文件返回给用户代理。有关详细讨论,请参阅AreES6modulesinbrwosersgoingtogetloadedlevel-by-level以详细讨论此问题。0x05charset属性给出脚本内容的编码方式;没有src的脚本不能设置该属性,模块脚本强制按照utf8解析。0x06noscript标签noscript标签告诉浏览器,如果你不支持脚本或者脚本被禁用,那么就给我看里面的内容。通常用作禁用脚本的回退。0x07最后一个脚本标签真精彩。如果觉得我的文章不错,可以关注我的知乎专栏:撸起袖子搞前端Segmentfault:mrcode的文章技术博客:blog.mrcodex.com推特:mrcodehang新浪微博:云航先生0x08参考文章html。spec.whatwg.org/dev/scripting.html#scriptingLanguageses6-modules-in-browsers-going-to-get-loaded-level-by-level
