如果将async defer prefetch preload @import link:media dns-prefetch
称之为对html文件的配置,那么这些配置对于初学者来说很难理解的,本文分为上下两个部分对这些概念进行分析,力求做到简单易懂。
4.7 测试7:使用preload利用空闲时间加载资源
首先这个"利用空闲"就已经明白的说出了这种做法是不阻塞的!
将index.html修改成如下所示:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="preload" href="http://localhost:3000/fast" as="script">
</head>
<body>
<h1>我出现了!</h1>
<button id="btn">点我翻页</button>
<script>
const btn = document.getElementById('btn');
const o = document.createElement('script');
o.src = "http://localhost:3000/fast";
btn.addEventListener('click', ()=>{
document.body.append(o);
})
</script>
</body>
</html>
需要注意的事情是:link中的as="script"一定要写,否则的话就不会起到任何作用!
在点击按钮之前,控制台中不会打印任何内容,网络面板所示为:
注意这里的优先级是:高
而在点击了按钮之后立马打印出fast
此时网络面板中并没有任何变化!
对比prefetch,可以发现,prefetch不一定要写as但是preload一定需要!
此外注意fast资源的图标,在prefetch加载完资源之后是空白的,而preload是由icon的,这就是为什么它非要指定资源的类型了;并且preload完成之后其响应和预览中是有值的。
4.8 测试8:验证浏览器请求css资源是采用并发的方式
请求两个css,名字分别为2.css和3.css,表示它们的耗时分别为2s和3s。 touch 2.css 3.css
css
:root{
color:pink;
}
:root{
background-color:pink;
}
然后修改后端服务器,增加两条路由,如下所示:
js
app.get('/2',(req,res)=>{
res.setHeader('Connection', 'close');
setTimeout( () => {
const fileContent = fs.readFileSync(path.join(__dirname, './2.css'));
res.end(fileContent);
} , 2000)
})
app.get('/3',(req,res)=>{
res.setHeader('Connection', 'close');
setTimeout( () => {
const fileContent = fs.readFileSync(path.join(__dirname, './3.css'));
res.end(fileContent);
} , 3000)
})
然后修改index.html中的内容如下所示:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" type="text/css" href="http://localhost:3000/2">
<link rel="stylesheet" type="text/css" href="http://localhost:3000/3">
</head>
<body>
<h1>我出现了!</h1>
</body>
</html>
打开index.html发现:
而对应的:
完成用时:3.02 秒
DOMContentLoaded:3.02 秒
加载时间:3.02 秒
所以起码在这个时候请求css是并发的。
接下来展示一下使用@import的不好之处:
修改3.css为:
css
@import url('http://localhost:3000/2');
:root{
background-color:pink;
}
修改index.html中的内容为:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" type="text/css" href="http://localhost:3000/3">
</head>
<body>
<h1>我出现了!</h1>
</body>
</html>
此时打开index.html,网络面板中的显示内容为:
完成用时:5.02 秒
DOMContentLoaded:5.02 秒
加载时间:5.02 秒
也就是说并行变成了串行,这肯定是有问题的!所以@import不被使用的原因也就在此了!
4.9 测试9:浏览器并发数目确定
修改index.html的内容为:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" type="text/css" href="http://localhost:3000/2">
<link rel="stylesheet" type="text/css" href="http://localhost:3000/3">
<link rel="stylesheet" type="text/css" href="http://localhost:3000/4">
<link rel="stylesheet" type="text/css" href="http://localhost:3000/5">
<link rel="stylesheet" type="text/css" href="http://localhost:3000/6">
<link rel="stylesheet" type="text/css" href="http://localhost:3000/7">
<link rel="stylesheet" type="text/css" href="http://localhost:3000/8">
<link rel="stylesheet" type="text/css" href="http://localhost:3000/9">
<link rel="stylesheet" type="text/css" href="http://localhost:3000/10">
</head>
<body>
<h1>我出现了!</h1>
</body>
</html>
然后在后端增加相应的路由
也不必增加对应的css文件了,让这些不同的路由指向相同的css文件也是可以的!
打开index.html发现:
也就是说排队的有三个,所以此时最大的并发请求数目为6个!
4.10 测试10:css的懒加载,使用media字段
在使用link加载css文件的时候,使用media字段来实现具体情景下才加载css的效果,将index.html改写为:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" type="text/css" href="http://localhost:3000/3" media="(max-width:40em)">
</head>
<body>
<h1>我出现了!</h1>
</body>
</html>
将浏览器最大化,然后访问index.html,网络面板如图所示:
完成用时:3.04 秒
DOMContentLoaded:40 毫秒
加载时间:3.04 秒
然后将浏览器最小化,再访问index.html:
居然是最高!
完成用时:3.03 秒
DOMContentLoaded:3.01 秒
加载时间:3.02 秒
于是得出结论:使用了media字段之后的link标签可以根据media所设定的条件来改变此资源的优先级,以及是否阻塞DOM的渲染!
不仅如此,media字段还会让浏览器在宽度大于40em和小于40em的时候表现出不同的样式!拖拽改变窗口的大小就能够看到这种变化了!
4.11 测试11:dns预加载
首先要知道本机的hosts文件在哪里,这样的话就可以捏造一个域名,强行开启dns解析:hosts文件的位置在C:\Windows\System32\drivers\etc,打开这个文件,并在最后一行追加:
127.0.0.1 supx
然后以管理员身份保存此文件。
接下来访问http://supx:8800看能否成功,成功的话则说明已经配置成功了。
然后就是如何清除dns缓存,清除了才能够让浏览器每一次都发起dns解析:
正确的做法是:ctrl+shift+delete清除缓存,然后ctrl+shift+R强制刷新页面,这样就可以将浏览器缓存的dns清除了。
然后改变index.html文件内容如下所示:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" type="text/css" href="http://localh<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- <link rel="stylesheet" type="text/css" href="http://supcon:3000/3" media="(max-width:40em)"> -->
<link rel="dns-prefetch" href="http://supcon">
</head>
<body>
<h1>我出现了!</h1>
<button id="btn">点我添加样式</button>
<script>
const btn = document.getElementById('btn');
const lk = document.createElement('link');
lk.rel = "stylesheet";
lk.type = "text/css";
lk.href = "http://supcon:3000/3";
lk.media = "(max-width:40em)";
btn.addEventListener('click', ()=>{
document.head.append(lk);
})
</script>
</body>
</html>
<body>
<h1>我出现了!</h1>
</body>
</html>
打开index.html然后等待一秒,点击按钮,网络面板上的信息如下:
可以看到dns解析过程只占用了5微秒;
然后删除dns预解析:
<link rel="dns-prefetch" href="http://supcon">
清除dns缓存之后,做相同的操作,效果为:
这时不要被它的比例迷惑了,这次整整用了61毫秒!
所以dns-prefetch显然是有效的!但是这5微秒也说明了,即使使用dns-prefetch在这个事情上还是要花费时间的。