现代浏览器性能优化-CSS篇
我来填坑了,CSS篇终于写出来了,如果你没看过前面的JS篇,可以在这里观看。
众所周知,CSS的加载会阻塞浏览器渲染或是引起浏览器重绘,目前业界普遍推荐把CSS放到
<head>中,防止在CSS还没加载完,DOM就已经绘制出来了,造成CSS加载完成后的重绘。那在现代浏览器中我们有没有办法提高首屏渲染速度那?
你是不是经常在第一次打开某个网站的时候看到这种情况,本来的页面是这样的
实际上刚加载出来的是这样的
字体文件没加载出来,或者加载的太慢了
理解CSS解析过程
以下面这段HTML为例,解释一遍CSS加载解析的过程。
<html>
<head>
<!-- headStyle.css中存在字体文件webfont.woff2 -->
<link rel="stylesheet" type="text/css" href="/headStyle.css">
</head>
<body>
<p>Text</p>
<link rel="stylesheet" type="text/css" href="/bodyEndStyle.css">
</body>
</html>
浏览器自上而下读取HTML文档,当发现headStyle.css的时候,停止Parser HTML,开始下载headStyle.css,解析headStyle.css的过程中发现字体文件webfont.woff2,开始下载webfont.woff2,并继续解析css生成CSSStyleSheet。解析完毕后,继续Parser HTML,当发现p标签时,会将p标签结合当前的CSSStyleSheet展示出来,此时用户屏幕中已经有p标签的内容了。当浏览器发现bodyEndStyle.css时,就会下载headStyle.css,解析CSS,然后更新CSSStyleSheet,这时会引起一次重绘。当字体下载完毕的时候也会引起一次重绘。
这个过程中,有两个非常严重的问题。一、如果headStyle.css文件很大,浏览器需要解析很多行CSS后才能还有个字体文件需要下载,其实此时已经很晚了,字体下载时间稍长一点,就会出现我前面截图提到的问题。二、bodyEndStyle.css中如果存在p标签对应的样式,那p标签的样式会在bodyEndStyle.css解析完成后,改变一次样式,很影响体验。
如何解决这些问题那?其中也会用到一些JS篇中提到的点,如果没看过,建议先看看。
优化核心依旧是减少下载时间
JS篇中的预先解析DNS(dns-prefetch)依旧适用,提前解析CSS文件所在域名的DNS。
Preload
因为CSS已经在head中,我们不需要为css加preload属性了,但是css中用到的字体文件,一定要在所有css之前proload上。
<link rel="preload" href="/webfont.woff2" as="font">
首页CSS内联,非必要CSS异步加载
首页用到的CSS内联写在<head>中,其余CSS均采用异步加载,可以采用这种自己实现的加载CSS的方法,在合适的需要时加载需要的css
function LoadStyle(url) {
try {
document.createStyleSheet(url)
} catch(e) {
var cssLink = document.createElement('link');
cssLink.rel = 'stylesheet';
cssLink.type = 'text/css';
cssLink.href = url;
var head = document.getElementsByTagName('head')[0];
head.appendChild(cssLink)
}
}
如果你使用webpack,那就更轻松了,使用import函数,大致如下
// 在a.js模块中直接引入css
import 'style.css'
// 在需要a.js模块的地方
improt('path-of-a.js').then(module => {})
webpack打包后,其实是把style.css打包进了a.js,在异步加载a.js的时候,会将style.css中的代码插入haed标签中。
终极完美结构
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Faster</title>
<link rel="dns-prefetch" href="//cdn.cn/">
<link rel="preload" href="//cdn.cn/webfont.woff2" as="font">
<link rel="preload" href="//cdn.cn/Page1-A.js" as="script">
<link rel="preload" href="//cdn.cn/Page1-B.js" as="script">
<link rel="prefetch" href="//cdn.cn/Page2.js">
<link rel="prefetch" href="//cdn.cn/Page3.js">
<link rel="prefetch" href="//cdn.cn/Page4.js">
<style type="text/css">
/* 首页用到的CSS内联 */
</style>
</head>
<body>
<script type="text/javascript" src="//cdn.cn/Page1-A.js" defer></script>
<script type="text/javascript" src="//cdn.cn/Page1-B.js" defer></script>
</body>
</html>
在JS篇)中,我已经解释过这套结构中JS的执行顺序了,本篇只是加入了CSS和字体。至此,我心中终极完美的页面HTML结构就是这样了。
如果你对异步加载CSS的方案感兴趣,欢迎留言与我讨论!
扩展阅读
现代浏览器性能优化-CSS篇的更多相关文章
- 性能优化-css,js的加载与执行
前端性能优化 css,js的加载与执行 javascript是单线程的 一个网站在浏览器是如何进行渲染的呢? html页面加载渲染的过程 html渲染过程的一些特点 顺序执行,并发加载 词法分析 并发 ...
- 前端性能优化JavaScript篇
关于前端性能优化的讨论一直都很多,包罗的知识也很多,可以说性能优化只有更好,没有最好.前面我写了一篇关于css优化的总结文章,今天再从javascript方面聊一聊. 1.从资源加载方面来说,浏览器的 ...
- 浏览器兼容性之Css篇
本文与上一篇随笔<浏览器兼容性之Javascript篇>有一定关联,下来我会继续不断总结,旨在解决浏览器兼容性,对遇到类似问题的同仁有所帮助,如有更多解决浏览器兼容性的案例还望大家分享一起 ...
- 浏览器兼容性汇总--CSS篇
目录 CSS篇 1. cursor:hand VS cursor:pointer 2. innerText在IE中能正常工作,但在FireFox中却不行 3. ...
- PHP性能优化 -理论篇
什么情况下,遇到了PHP性能问题? 1 PHP语法使用的不恰当 2 使用PHP语言做不了它不擅长做的事 3 用php语言连接的服务不给力 4 PHP自身的短板 5 我也不 ...
- (转)Android性能优化——工具篇
Android性能优化是Android开发中经常遇见的一个问题,接下来将对Android性能优化方面的知识点做一个简单的梳理和总结,将从工具和代码两方面进行梳理.所谓工欲善其事必先利其器,本文首先来看 ...
- 前端性能优化 css和js的加载与执行
一个网站在浏览器端是如何进行渲染的? html本身首先会被渲染成 DOM 树,实际上 html 是最先通过网址请求过来的,请求过来之后,html 本身会由一个字节流转化成一个字符流,浏览器端拿的就是字 ...
- Mysql优化系列之查询性能优化前篇2
接前一篇,这一篇主要总结下几个经常要用的命令 命令一:explain+sql mysql> explain select * from servers; +----+-------------+ ...
- android 性能优化-电量篇
消耗电量的几个主要原因.功能:1.大数据量的网络传输(网络)2.不停的网络切换(网络)3.解析大量的数据(CPU) 关于网络方面的优化: .网络请求之前,检查网络连接.没有网络连接不进行请求 .判断网 ...
随机推荐
- nginx 安全配置和限制访问
nginx基本安全配置 配置ssl证书 listen 443 ssl; ssl_certificate /usr/local/nginx/conf/server.crt; ssl_certificat ...
- Temporal IR (Chapter3 -Temporal Infroamtion Extraction)
不管是文档,还是查询中,都显式或者隐式地包含了可以被利用的时间信息. 提取出来的时间信息可以用作构成“时间简历”(temporal profile)用于多种对象,比如实体和事件. 在时间信息中,最容易 ...
- Jmeter做HTTP接口测试
接口测试概述:https://www.cnblogs.com/mawenqiangios/p/7886115.html Jmeter接口测试教程:https://www.cnblogs.com/hou ...
- MySQL之创建用户和授权
一 权限管理 我们知道我们的最高权限管理者是root用户,它拥有着最高的权限操作.包括select.update.delete.update.grant等操作.那么一般情况在公司之后DBA工程师会创建 ...
- list列表
list列表 list:一个有序的集合 创建列表 语法格式: 列表名 = [元素1, 元素2, 元素3…….,元素n] 注:列表中的元素⽤逗号隔开. 注:列表⾥⾯的元素可以是不同类型的数据. 列表元素 ...
- docker&git&gitlab-安装/部署/新建
--安装gcc yum -y install gcc --安装g++ yum -y install gcc-c++ --安装编译所需的包 yum -y install curl-devel expat ...
- Python语言中各种进制相互转换
目录 Python语言中各种进制相互转换 将二进制.八进制.十进制的数分别转换成十进制的方法 将十进制转换成二进制.八进制.十六进制 Python语言中各种进制相互转换 本文参考自https://ww ...
- BZOJ4516 SDOI2016生成魔咒(后缀自动机)
本质不同子串数量等于所有点的len-parent树上父亲的len的和.可以直接维护. #include<iostream> #include<cstdio> #include& ...
- [Vue]vue-router嵌套路由(子路由)
总共添加两个子路由,分别命名Collection.vue(我的收藏)和Trace.vue(我的足迹) 1.重构router/index.js的路由配置,需要使用children数组来定义子路由,具体如 ...
- 解决 Linux grep 不高亮显示
今天偶然发现一个问题,在 grep 日志的过程中,搜出来一大坨但是被 grep 的那一段未高亮显示,属实有些难受,高亮显示是 Linux 的高亮本来就是 Linux 的功能,与连接工具(我用的 xsh ...