关键词:异步加载脚本、MIME、Preload、内容安全策略
<script>
标签
<script type="application/javascript" src="" defer></script>
<script type="application/javascript" src="" sync></script>
复制代码
- async="async" 异步执行脚本
- defer="defer" 脚本在页面完成解析时执行。 如果不使用async、defer,在浏览器继续解析之前会立即读取并执行脚本
- type="MIME-type" 规定脚本的MIME类型
MIME
MIME 描述消息内容类型的因特网标准。MIME类型就是设定某种扩展名的文件用哪种应用程序来打开的方式类型。浏览器通常使用MIME类型而不是文件扩展名来确定如何处理文档。
MIME类型由两部分组成:媒介类型和子类型。
媒介类型 | 描述 |
---|---|
text | 表示文件是普通文本, text/plain, text/javascript, text/css, text/html |
image | 图像,包括动图, image/gif, image/png, image/x-icon |
audio | 音频文件, audio/midi, audio/ogg, audio/wav |
video | 视频文件, video/webm, video/ogg |
application | 表明是某种二进制文件, application/octet-stream, application/xml, application/javascript |
multipart | 复合文件类型, multipart/form-data, multipart/byteranges |
所有的text javascript类型已经被废弃,推荐使用application/JavaScript
<link>
标签
在HTML中,<link>
标签没有结束标签。rel属性用于定义当前文档与被链接文档之间的关系。
参考链接:
关于Preload, 你应该知道些什么?
Link Preload 标签
深入研究Chrome:Preload与Prefetch原理,及其优先级
dns-prefetch
DNS Prefetch 是一种 DNS 预解析技术。当你浏览网页时,浏览器会在加载网页时对网页中的域名进行解析缓存,这样在你单击当前网页中的连接时就无需进行 DNS 的解析,减少用户等待时间,提高用户体验。
<!-- off为关闭,ON为开启 -->
<meta http-equiv="X-dns-prefetch-control" content="on" />
<link rel="dns-prefetch">
复制代码
Prefetch
<link rel="prefetch" as="script" href="example.js">
复制代码
当确定网页在未来(下一页)一定会使用某资源时,可以通过prefetch提前请求资源并且缓存以供后续使用。但具体什么时候请求这个资源由浏览器决定。 页面跳转时prefetch发起的请求不会中断。该方法的加载优先级很低,一般用来提高下一个页面的加载速度。
Preload
Preload是一项新的web标准,旨在提高性能和为开发人员提供更细粒度的加载控制。Preload可以让开发者自定义资源的加载逻辑,且无需忍受基于脚本的资源加载器带来的性能损失。 preload是声明式的fetch,可以强制浏览器请求资源,同时不阻塞文档onload事件。
对于当前页面有必要的资源使用preload
,对于可能在将来的页面中使用的资源使用prefetch
。 preload
和prefetch
请求的资源都缓存在HTTP缓存中。
link标签不需要关闭
声明式获取指令 declarative fetch directive
<link rel="preload" as="script" href="example.js">
复制代码
onload
Preload支持onload事件,可以自定义资源加载完后的回调函数。
<link rel="proload" href="test.js" as="script" onload="console.log('finish');">
复制代码
as
preload的as
属性,告诉浏览器加载的是什么资源。常用的as属性值有:
script, style, image, media, document, font
通过设置as
属性可以实现:
- 浏览器可以设置正确的资源加载优先级
- 浏览器可以确保请求是符合内容安全策略的
- 浏览器根据
as
的值发送正确的accept头部信息 - 浏览器根据
as
的值得知资源类型。因此当获取的资源相同时,浏览器能够判断前面获取的资源能否重用。
忽略as
或者设置错误的值会使preload等同于XHR异步请求。但浏览器不知道加载的是什么,会赋予此类资源非常低的加载优先级。
预加载器 Preloader
令牌化阶段tokenization : 输出对HTML对早期解析结果
预加载器Preloader : 找到包含资源的标签,将这些资源的URL收集起来
读取器fetcher:根据这些资源对页面加载速度的影响进行有序的加载
preload的常用用法:
peoload的主要用途是提前加载资源,在需要的时候直接执行,将加载和执行分开。
- 使用preload动态加载js脚本,但是不立即执行,之后再通过
<script>
执行脚本
// 预先加载脚本
var link = document.createElement('link');
link.rel = 'preload';
link.as = 'script';
link.href = 'myscript.js';
document.head.appendChild(link);
// 执行脚本
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'myscript.js';
document.body.appendChild(script);
复制代码
- 提前加载字体,解决字体图标闪的问题
<link rel="preload" as="font" type="font/woff" href="myfont.woff" crossorigin>
复制代码
一定要加crossorigin
,即使同源
- 基于标记语言的异步加载
<script async></script>
可以实现异步加载,但是会阻塞window的onload事件。可以通过preload的onload事件实现资源的异步加载。先用link preload加载资源到本地,资源加载完后通过onload事件设置回调,使用资源或执行脚本。
异步记载样式文件
<link rel="preload" as="style" href="async_style.css" onload="this.rel='stylesheet';">
复制代码
异步加载js脚本
<link rel="preload" as="script" href="async_script.js" onload="
var script = document.createElement('script');
script.src = this.href;
document.body.appendChild(script);
">
复制代码
兼容性
判断浏览器是否支持preload
var DOMTokenListSupports = function(tokenList, token) {
if (!tokenList || !tokenList.supports) {
return;
}
try {
return tokenList.supports(token);
} catch (e) {
if (e instanceof TypeError) {
console.log("The DOMTokenList doesn't have a supported tokens list");
} else {
console.error("That shouldn't have happened");
}
}
};
var linkSupportsPreload = DOMTokenListSupports(document.createElement("link").relList, "preload");
if (!linkSupportsPreload) {
// Dynamically load the things that relied on preload.
}
复制代码
内容安全策略 Content-Security-Policy
网站通过发送csp头部,告诉浏览器什么是被授权执行的,什么是被禁止的。CSP被称为解决XSS攻击的神器,可以解决潜在的跨站脚本安全问题。 Content-Security-Policy 配置并启用后,不符合csp的外部资源会被阻止加载。
CSP的使用方式:
- 在HTTP Header上使用
"Content-Security-Policy": 策略
复制代码
- HTML 标签上使用
<meta http-equiv="Content-Security-Policy" content="策略">
复制代码
两个同时存在的话,优先采用HTTP头部设置的策略。
策略由一个或多个CSP指令组成,多个指令之间用英文分号分隔,多个指令值之间用空格分隔。
常用的CSP指令、值:
CSP指令 | 描述 |
---|---|
default-src | 默认加载策略 |
script-src | 对于JavaScript脚本的加载策略 |
style-src | 对于样式的加载策略 |
img-src | 图片的加载策略 |
object-src | 显示插件来源,如flash |
frame-src | |
media-src | |
report-uri | 请求资源不被允许时,向该地址提交日志 |
CSP指令值 | 描述 |
---|---|
* | 允许任何内容 |
'none' | 不允许加载任何内容 |
'self' | 允许来自相同源的资源 |
data: | 允许data:协议,如base64编码的图片 |
www.host.com | 允许加载指定域名的资源 |
unsafe-inline | 允许加载inline资源,如style属性,inline css, inline js |
unsafe-eval | 允许加载动态js代码 |
Content-Security-Policy: default-src 'self'
Content-Security-Policy: default-src http://host.com https://aaa.com; frame-src 'none'; object-src 'none'
复制代码