preload 让加载和解析解耦

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: preload 让加载和解析解耦

preload 让加载和解析解耦


TL;DR

  • preload本质:preload 是声明式的 fetch,可以改变浏览器加载资源的优先级,强制浏览器请求资源,同时不阻塞文档 onload 事件,也因此可以将 load 事件与脚本解析过程解耦
  • prefetch本质:让浏览器空闲的时候加载下一页可能需要的资源,同样的load和解析解耦
  • dns-fetch,让浏览器提前做dns预解析,当静态资源和html不在同一个域的时候,特别好用
  • async,defer是script的属性,其让html解析与下载并行,但是async下载完之后立即执行,而defer是html解析完之后再执行,一般按照顺序执行,但据说不是百分百靠谱

概述

一般写html页面,script写在body结束标签前,这样只有当遇到script标签的时候,才会加载执行,费加载时间不科学吖!尽管大多数基于标记语言的资源能被浏览器的预加载器(Preloader)提前加载,但还是不尽如人意!

理想情况是,先从文档需要的资源,根据优先级,下载到本地,等到需要的时候,就可以直接使用或者解析执行!

然后!对!preload就可以干这个事!可随时关注preload的动态,就目前很多现代浏览器已经支持!

preload大白话的意思是,”嗨,浏览器!这个资源在这个页面后面会用到,现在先加载它吧。“

好处

好处远不止上面的:

  • 本质!preload 是声明式的 fetch,可以改变浏览器加载资源的优先级,强制浏览器请求资源,同时不阻塞文档 onload 事件,也因此可以将 load 事件与脚本解析过程解耦
  • 资源的提前加载。<link rel="preload" href="late_discovered_thing.js" as="script">
  • 字体的提前加载。<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
  • 动态加载,但不执行。加载某一资源但却不想立即执行它,而是想在特定的时机执行。后面细说代码。
  • 基于标记语言的异步加载。<link rel="preload" as="style" href="asyncstyle.css" onload="this.rel='stylesheet'">,加载完之后就可以应用到文档里了,script也同理,这里的onload是指window的onload事件,在加一些统计脚本的时候挺合适,不影响页面的onload,<link rel="preload" as="script" href="async_script.js" onload="var script = document.createElement('script'); script.src = this.href; document.body.appendChild(script);">
  • 响应式加载。preload是在link标签上,也就是还可以配合media属性,能让浏览器加载自己需要的资源。<link rel="preload" as="image" href="map.png" media="(max-width: 600px)"> <link rel="preload" as="script" href="map.js" media="(min-width: 601px)">
  • 检测浏览器是不是支持preload,var isSupportPreload = document.createElement("link").relList && document.createElement("link").relList.supports('preload')

怎么使用preload

先说说link标签

先说下link标签的使用。

  • link规定了外部资源与当前文档的关系!
  • 于是link有不可或缺的两个属性,href外部资源的路径,rel外部资源与当前文档的关系,rel其实relation的缩写,但因为多数用于css,所以rel是stylesheet的时候,是可以省略的
  • link标签只能出现在head
  • 有全局属性和onload事件,onload事件是指文档所有资源加载完之后
  • media:这个属性规定了外部资源适用的媒体类型。它的值必须是"媒体查询"。这个属性使得用户代理能选择最适合设备运行的媒体类型。<link rel="stylesheet" media="(max-width: 800px)" href="example.css" />
  • type这个属性被用于定义链接的内容的类型。这个属性的值应该是像text/html,text/css等MIME类型。这个属性常用的用法是定义链接的样式表,最常用的值是表明了CSS的text/css。

preload是在link上的

  • 使用preload很简单,就是link的rel="preload",href是仍然是资源路径,然后加上as来说明加载的内容的类型就可以了,常用的"script" "style" "image" "media" "document"
  • preload加载字体的时候,crossorigin 属性是必须的,即便是字体资源在自家服务器上,因为用户代理必须采用匿名模式来获取字体资源。type 属性可以确保浏览器只获取自己支持的资源。比如Chrome 支持 WOFF2,看到这个就下载了,遇到不识别的类型就忽略
<!-- js -->
<link rel="preload" href="static.js" as="script" onload="preloadFinished()">
<!-- css -->
<link rel="preload" href="static.css" as="style" onload="preloadFinished()">
<!-- 字体,注意crossorigin和type的增加 -->
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>

细说,动态加载,但不执行

其实动态加载就是插入带preload的link,执行的时候,动态的创建script。

function loadScript(url){
    var link = document.createElement("link");
    link.href = url
    link.rel = "preload";
    link.as = "script";
    document.head.appendChild(link);
}
function execScript(url){
    var script = document.createElement("script");
    script.src = url;
    document.body.appendChild(script);
}
// 加载这个js,但不执行
loadScript("myscript.js")
// 某个时机执行
setTimeout(function(){
    execScript("myscript.js")
},1000)

preload的坑

注意吖,不是说加载了就是执行!!!!!

也就是preload只管加载!!!

换句话说,你买东西,preload相当于快递到你家门口了,但是你只有拆了包裹才算是使用!!!

代码的体现就是,以前的<link href="xx.css"><script src="xxx.js">还是要写在相应的位置的!

然后在head头里加上<link rel="preload" href="xx.css" as="style"><link rel="preload" href="xxx.js" as="script">,preload是锦上添花的!

浏览器加载机制

我觉得吧,先去知道浏览器加载机制之后,才能更加体会到preload的美!

这边简单的总结下,浏览器的加载机制:

  • 资源分类。html,css,js...
  • 安全策略检查。是否加载某处的资源
  • 资源优先级计算。html、css、font资源 => preload资源、script、xhr请求 => 图片、语音、视频 => prefetch预读取的资源(多用于dns)
  • 综合安全策略和优先级,开始下载资源
  • 谷歌控制台查看资源优先级的方法:打开开发者工具 -> 点击network -> 刷新页面 -> 在出现的表格的表头那行右击(就是Name,type,size...)选择Priority

prefetch与preload

prefetch相当于说,“嗨,浏览器,下个页面可能要用到这个资源,你闲着无聊就帮我加载下呗~”。 用法跟preload差不离,link的rel="prefetch"

和preload区别:

  • preload是让浏览器提前加载当前页面比较重要的资源,,prefetch是让浏览器没活的时候加载下个页面可能用到的资源
  • prefetch并没有同域的限制,但preload有
  • 都不会影响onload事件,准备说有点load事件和解析解耦的感觉
  • 当页面上使用到这个资源时候 preload   资源还没下载完,这时候不会造成二次下载,会等待第一次下载并执行脚本。prefetch差不多吧。
  • 对于 preload 来说,一旦页面关闭了,它就会立即停止 preload 获取资源,而对于 prefetch 资源,即使页面关闭,prefetch 发起的请求仍会进行不会中断。

随手说下dns-prefetch

先说域名只是服务器ip地址的美化,也就是虽然请求域名,但实际是先请求dns服务器,dns服务器返回域名所代表的真正的服务器ip,浏览器再向服务器发送请求。

dns-prefetch就是让浏览器先将域名发给dns服务器,让浏览器知道,域名所指的真正的服务器,之后在发送请求的时候,就直接发给服务器了。

简单的一行就能让支持的浏览器提前解析DNS。也就是说在浏览器请求资源时,DNS查询就已经准备好了。

使用方式<link rel="dns-prefetch" href="//example.com">

使用场景:

  • 项目的静态资源和html不在同一个域上
  • 有重定向的域名

还有async,defer

直接引用这个回答,当浏览器碰到 script 脚本的时候:

  • 没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。<script src="script.js"></script>
  • 有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。<script async src="script.js"></script>
  • 有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。<script defer src="myscript.js"></script>

preload的好处

w3c的preload,一眼可以看到支持

浏览器加载机制

prefetch和preload

一箩筐的预取技术

目录
相关文章
|
7月前
|
缓存 图形学 UED
U3D开发技术深度解析:异步场景加载与资源管理优化策略
【7月更文第11天】在Unity3D(简称U3D)游戏开发中,优化场景加载与资源管理是提升用户体验的关键一环。通过实现高效的异步场景加载和智能的资源管理策略,我们能显著缩短玩家的等待时间,提升游戏流畅度。本文将详细介绍这两种技术的应用,并提供实用的代码示例。
583 0
|
XML Java 数据格式
我滴妈!人事竟然问我Spring BeanDefinition是如何帮我们解析和加载的?
我滴妈!人事竟然问我Spring BeanDefinition是如何帮我们解析和加载的?
69 0
我滴妈!人事竟然问我Spring BeanDefinition是如何帮我们解析和加载的?
|
9月前
|
移动开发 iOS开发
非标准h5字符串的WKWebView展示前的解析与插入属性或标题头与解决WKWebView无法加载视频首帧问题
非标准h5字符串的WKWebView展示前的解析与插入属性或标题头与解决WKWebView无法加载视频首帧问题
76 1
|
8月前
|
Java 编译器
全面解析JVM加载中初始化的时机
全面解析JVM加载中初始化的时机
|
8月前
|
数据采集 前端开发 JavaScript
Python爬虫技术:动态JavaScript加载音频的解析
Python爬虫技术:动态JavaScript加载音频的解析
|
9月前
|
存储 安全 Java
Trembling ! Java类的加载过程详解(加载验证准备解析初始化使用卸载)
Trembling ! Java类的加载过程详解(加载验证准备解析初始化使用卸载)
82 0
|
XML 存储 前端开发
解析 SpringMVC 父子容器及九大内置组件加载过程
解析 SpringMVC 父子容器及九大内置组件加载过程
132 1
|
XML Java 数据格式
Spring源码深度解析02-debug式查看如何加载AnnotationConfig
Spring源码深度解析02-debug式查看如何加载AnnotationConfig
127 0
Spring源码深度解析02-debug式查看如何加载AnnotationConfig

热门文章

最新文章

推荐镜像

更多