Chrome打算改变 的加载方式,当 link 出现在
中时,就变得非常明显了。在blink-dev的文章中,它的影响和性能尚不明确,所以我想在这里深入讲讲。当前加载CSS的方法
<head> <link rel="stylesheet" href="/all-of-my-styles.css"></head><body> …content…</body>
CSS会阻塞渲染,用户需要等待 all-of-my-styles.css 整个加载完,否则屏幕一直是白色的。
一个网站的CSS样式分成一个两个文件存放是非常正常的,也就是说用户必须额外加载一大堆的并不会应用于当前页面的样式规则。因为网站会包含很多类型的页面,其中包含的“组件”也非常多,在组件级别整理CSS文件的话,对于HTTP/1协议会影响性能。
对于SPDY和HTTP/2来说则并非如此,许多小规模的资源可以以较小的开销生成,以及独立缓存。
<head> <link rel="stylesheet" href="/site-header.css"> <link rel="stylesheet" href="/article.css"> <link rel="stylesheet" href="/comment.css"> <link rel="stylesheet" href="/about-me.css"> <link rel="stylesheet" href="/site-footer.css"></head><body> …content…</body>
这解决了冗余加载的问题,但意味着你需要先知道:当你输出
时,页面将包含什么内容,可以防止streaming。另外,浏览器在渲染页面内容之前,还是需要先下载所有的CSS文件。一个 loading /site-footer.css 文件的缓慢加载,就可以导致页面所有内容的渲染延迟。查看DEMO
当前加载CSS最先进的方式
<head> <script> // https://github.com/filamentgroup/loadCSS !function(e){"use strict" var n=function(n,t,o){function i(e){return f.body?e():void setTimeout(function(){i(e)})}var d,r,a,l,f=e.document,s=f.createElement("link"),u=o||"all" return t?d=t:(r=(f.body||f.getElementsByTagName("head")[0]).childNodes,d=r[r.length-1]),a=f.styleSheets,s.rel="stylesheet",s.href=n,s.media="only x",i(function(){d.parentNode.insertBefore(s,t?d:d.nextSibling)}),l=function(e){for(var n=s.href,t=a.length;t--;)if(a[t].href===n)return e() setTimeout(function(){l(e)})},s.addEventListener&&s.addEventListener("load",function(){this.media=u}),s.onloadcssdefined=l,l(function(){s.media!==u&&(s.media=u)}),s} "undefined"!=typeof exports?exports.loadCSS=n:e.loadCSS=n}("undefined"!=typeof global?global:this) </script> <style> /* The styles for the site header, plus: */ .main-article, .comments, .about-me, footer { display: none; } </style> <script> loadCSS("/the-rest-of-the-styles.css"); </script></head><body></body>
上面的代码中,有一些内联样式使得我们可以进行快速的初始渲染,然后隐藏我们还没有加载样式的内容,接着使用JavaScript异步加载剩下的CSS。剩下加载的CSS会重写 .main-article 中的 display: none 。
这种方法是 性能方面 的 专家 建议 的,以获得快速的初始渲染,也不无道理:
查看DEMO
在现实世界中,我做了这个 wiki-offline ,是有效果的 :
在3g网络中,初始渲染快了0.6秒。完整的结果 前 对比结果 后 对比。
但也有一些不足:
它需要一个(小)JavaScript库
不幸的是,这是由于WebKit的实现情况。一旦页面加了 ,WebKit会阻塞渲染,直到样式表加载完成,即使是通过JavaScript加载样式表。
在Firefox和IE/Edge中,通过JS加载样式表是完全异步的。稳定版的Chrome目前还是WebKit的方式,但在Chrome的Canary版本中,我们切换成了和Firefox/Edge一样的方式。
你被限制在两个阶段加载
在上面的模式中,内联CSS使用 display:none 隐藏没有样式的内容,然后异步加载CSS来解决。如果你的CSS文件多于两个或者更多,它们可能不会按照顺序加载,这会导致加载过程中内容错乱:
查看DEMO
内容错乱,还带有 弹出式广告 ,是非常糟糕的用户体验。
因为你被限制了只能在两个阶段加载,你必须选择第一次渲染加载什么,然后再加载什么。你当然希望“显眼”的内容被快速渲染,但是“页面排版”是依赖于窗口的。相当艰难,你必须选择一个适合所有情况的解决方案。
更新:如果你想要让事情变得复杂,你可以使用CSS自定义属性建立一个类似渲染依赖树的东西,这里有一篇使用自定义属性控制CSS加载的 文章 。
一种更简单更好的方法
<head></head><body> <!-- HTTP/2 push this resource, or inline it, whichever's faster --> <link rel="stylesheet" href="/site-header.css"> <header>…</header> <link rel="stylesheet" href="/article.css"> <main>…</main> <link rel="stylesheet" href="/comment.css"> <section class="comments">…</section> <link rel="stylesheet" href="/about-me.css"> <section class="about-me">…</section> <link rel="stylesheet" href="/site-footer.css"> <footer>…</footer></body>
这个方法是,对于每个 ,加载样式表时,阻塞渲染其后续内容,但允许在它之前的内容先渲染。样式表是并行加载的,但是按照顺序应用。这样 也变得和 有点像了。
我们来看看如果上面这个网站的标题header,正文内容article和footer,这些内容的CSS先加载,然后其它的挂起,页面结果会如何:
- 标题:渲染
- 正文:渲染
- 评论:没有渲染,它前面的CSS还没有加载( /comment.css )
- 关于我:没有渲染,它前面的CSS还没有加载( /comment.css )
- Footer:没有渲染,它前面的CSS还没有加载( /comment.css ),尽管它本身的CSS已经加载,但是被阻塞了
这是一个顺序渲染的页面。你不需要决定什么内容是“明显位置”,只需要在页面组件实例化之前引入该组件的CSS即可。它完全兼容streaming,因为你不需要输出 ,直到你需要它。
当使用内容决定布局的布局系统(如表格和flexbox)时,你需要注意避免加载过程中内容错位。这并不是新出现的问题,但渐进式渲染会导致这个问题更频繁地暴露。你可以hack flexbox来解决,但是CSS grid对于整体页面布局是 更好的系统 (flexbox对于较小组件依旧是非常棒的)。
Chrome的改变
HTML规范 没有包含页面被CSS阻塞时如何渲染,它不鼓励在 body 中写 ,但是所有的浏览器都允许这一写法。当然,浏览器都有自己解决 body 中的 link 的方式。
- Chrome & Safari :一旦发现 ,立刻停止渲染,直到所有已发现的样式表都加载完成再继续渲染。这通常会导致 前面尚未渲染的内容也被阻塞。
- Firefox : head 中的 会阻塞渲染,直到所有已发现的样式表加载。body中的 不会阻塞渲染,除非 head 中的样式表已经阻塞渲染。这会导致页面无样式内容闪烁(FOUC)。
- IE/Edge :阻塞解析器直到样式表加载完成,但允许 前面的内容渲染。
在Chrome,我们也喜欢IE/Edge的行为,所以我们将向它看齐。也就是上面描述的CSS渐进式渲染的模式。我们正努力把它变为标准,从允许
中加入 开始。目前,Chrome/Safari的行为是向下兼容,它只会阻塞它需要的渲染时间更长。Firefox的行为稍微复杂,但有一个解决方法...
Firefixing
因为Firefox并不经常因为 body 中的 link 阻塞渲染,我们需要解决它以避免FOUC。值得庆幸的是,这并不难,因为 <script> 可以阻塞解析, 这样就可以等待挂起的样式表加载完成: </script>
<link rel="stylesheet" href="/article.css"><script> </script><main>…</main>
该脚本元素必须是非空的,放个空格就好了。
看看实际的应用情况
查看DEMO
Firefox和Edge/IE会给你一个可爱的渐进式渲染,而Chrome和Safari在所有CSS加载完成之前都是无样式的白色屏幕。目前Chrome/Safari并不比你把所有的样式表放在
中更糟糕,所以你现在可以开始使用这个方法。在接下来的几个月里,Chrome将迁移到Edge模型,用户将得到更快的渲染。所以我们可以尝试了!一个更简单的只需加载你需要的CSS的方法,然后得到一个更快的渲染的过程。
感谢 @lukedjn 、Paul Lewis和Domenic Denicola的改正建议。特别感谢Boris Zbarsky帮我理解了Firefox的行为。还有Paul想出的“Firefixing”的技巧。
本文根据 @Jake 的《 The future of loading CSS 》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处: https://jakearchibald.com/2016/link-in-body/ 。
彦子
在校学生,本科计算机专业。逗比一枚,热爱前端热爱生活,喜欢CSS喜欢JavaScript喜欢SVG,爱玩PS玩AI玩啊逗比的软件。努力向上,厚积薄发。

WebDevelovermentReliesonHtml,CSS和JavaScript:1)HTMLStructuresContent,2)CSSStyleSIT和3)JavaScriptAddSstractivity,形成thebasisofmodernWebemodernWebExexperiences。

HTML的作用是通过标签和属性定义网页的结构和内容。1.HTML通过到、等标签组织内容,使其易于阅读和理解。2.使用语义化标签如、等增强可访问性和SEO。3.优化HTML代码可以提高网页加载速度和用户体验。

htmlisaspecifictypefodyfocusedonstructuringwebcontent,而“代码” badlyLyCludEslanguagesLikeLikejavascriptandPytyPythonForFunctionality.1)htmldefineswebpagertuctureduseTags.2)“代码”代码“ code” code code code codeSpassSesseseseseseseseAwiderRangeLangeLangeforLageforLogageforLogicIctInterract

HTML、CSS和JavaScript是Web开发的三大支柱。1.HTML定义网页结构,使用标签如、等。2.CSS控制网页样式,使用选择器和属性如color、font-size等。3.JavaScript实现动态效果和交互,通过事件监听和DOM操作。

HTML定义网页结构,CSS负责样式和布局,JavaScript赋予动态交互。三者在网页开发中各司其职,共同构建丰富多彩的网站。

HTML适合初学者学习,因为它简单易学且能快速看到成果。1)HTML的学习曲线平缓,易于上手。2)只需掌握基本标签即可开始创建网页。3)灵活性高,可与CSS和JavaScript结合使用。4)丰富的学习资源和现代工具支持学习过程。

AnexampleOfAstartingTaginHtmlis,beginSaparagraph.startingTagSareEssentialInhtmlastheyInitiateEllements,defiteTheeTheErtypes,andarecrucialforsstructuringwebpages wepages webpages andConstructingthedom。

如何设计菜单中的虚线分割效果?在设计菜单时,菜名和价格的左右对齐通常不难实现,但中间的虚线或点如何...


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能

记事本++7.3.1
好用且免费的代码编辑器

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境