一文解决async defer prefetch preload @import link:media dns-prefetch (下)

如果将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在这个事情上还是要花费时间的。

相关推荐
lpfasd1236 小时前
node-sass 停止维护!老项目迁移 Dart Sass 完整教程
前端·rust·sass
Data analyse4568 小时前
rnweb 回放数据量太大怎么办?分片存储与断点续传的实现思路
前端·网络·算法·数据分析
xiaogai_gai8 小时前
金蝶收料通知单查询策略实战教程:从源系统拉取到中间层落地的完整路径
java·前端·数据库
环境栈笔记9 小时前
指纹浏览器 WebRTC 怎么设置?从 ICE 候选、代理出口到功能验证
前端·人工智能·后端·自动化
赵大仁9 小时前
官网性能优化实战:LCP 3.2s → 2.1s、CLS 0.107 → 0,以及被我推翻的 6 个判断
前端·性能优化·cls·lcp·core web vitals
xiancai_xianyu10 小时前
Text2SQL落地生产库前,SQL要过哪三道闸
前端·数据库·sql·sql注入·text2sql·ai agent开发·企业级ai框架
小羊没烦恼!10 小时前
T-SQL查询进阶--理解SQL SERVER中的分区表
服务器·开发语言·前端·javascript·html
史瓦辛格10 小时前
给 DeepSeek Harness 写费用插件:把「这次会话花了多少钱」算准
前端·deepseek
星光不问赶路人10 小时前
Vue 3 + TypeScript 中 enum 的使用实践
前端·vue.js
鸥梨菌Honevid10 小时前
UVM 中 REQ 和 RSP 类型详解:从通信模型到 item_done 与 put_response
java·前端·servlet