主题越来越大了,因此需要采取各种措施来保证页面渲染速度及用户体验。这个地方也一直是我所特别注重的,因此打算使用一段时间来大量优化主题。
一、CSS优化
css优化大致有下面这些需要注意的点
- CSS会阻塞浏览器渲染,将其置于html顶部
- 减少CSS文件的请求数量
- 尽量避免使用CSS表达式
- 避免通配选择符,采用最右关键选择器进行优化
- 避免使用@import
- 删除无匹配的样式
- 异步加载CSS,加快页面渲染
等等。。。
本主题的样式基本由一个主样式 + N个第三方样式,因此从以下几点开始优化。
1. 合并第三方样式
有很多CSS文件都是非常小的,例如只有几K甚至几百B。对于这种CSS,并不是下载用时长,而是请求用时较长。因此,将这些较小的,长时间固定不改变的CSS合并为一个CSS样式是优化的一个方向。
根据上图及分析,圈出来的这三个css,暂时可以合并到一个css里面,他们符合较小的,且长时间固定不变的情况。
分开时
大小合计为2.4 + 1.6 + 7.6 = 11.6KB
耗时合计为 54 + 47 + 52 = 153MS
下面将他们合并为一个lib.css
可以看到,无论是大小还是耗时都有一定的下降,并且在实际使用时,第一个图里使用了CDN加速,而下方的图并没有使用cdn加速
2. 减少无用的css
这一项实际上应该是我的主题遗留的问题,最开始设计的时候,使用的是原主题的字体图标,之前也没有什么精力去优化修改。这次优化就将这个遗留问题给解决了
根据图可以看出,一共加载了两个字体图标,因此需要做一定的处理,将两个字体图标合为一个。这里只是记录一下,具体过程比较繁杂,不多赘述。
3. 异步加载css
异步加载css是我个人感觉本主题最需要做的一个处理。由于本主题加载的css有很多网络资源,尤其包含字体文件,如下所示
可以看出,字体文件在整个加载时间段还是占用了很大时间的。但字体文件作为项目必须的,且开源项目尽量不使用私人的资源路径。那么就只能从加载顺序和渲染时间来入手了
由于css加载的时候,会阻塞渲染,即在css文件请求、下载、解析完成之前,浏览器不会渲染任何内容(注意只是不会渲染而已),实际上这种阻塞是必须的,因为肯定要等待CSS加载完毕,页面才渲染,不然页面会特别丑。
但对于一个页面来说,并不是所有的CSS都是首页必须的,有的也许不会立即用到,例如上面的字体文件,即便不加载也不会特别丑。
这里共有很多种方法来实现这种异步加载。
- 使用JavaScript动态加载,并插入至DOM
- 设置link元素的media属性。当media属性不适用于当前的媒体类型时,优先级会被放低,将会在不阻塞页面的情况下进行加载。在加载完毕之后,将媒体类型设置为screen或者all
- 设置link元素的rel属性,将rel设置为可选样式表alternate。然后在加载完毕后,将rel重新设置为stylesheet
- 利用最新的属性,rel=”preload”,这个属性指出了如何异步加载资源,包括css资源。但如下图,目前浏览器的支持率还不是很乐观。但可以通过一些其他的方法,例如loadCSS进行polyfill,所以也还好
本次我采用了第二种方式,如下所示
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Noto+SerifMerriweather|Merriweather+Sans|Source+Code+Pro|Ubuntu:400,700|Noto+Serif+SC" media="noexist" onload="this.media='all'">
加载时,先设置media = “noexist”,然后设置onload=”this.media=’all’”来使得media变为all属性
现在页面加载时,将只会先加载主css,然后页面就可以呈现了,会给用户一种加载很快的感觉。
二、JS优化
JS优化算是最繁琐的步骤,JS可能会涉及到依赖、DOM等,因此需要重点注意。
JS优化大致有如下的步骤
- 合并JS
- 采用defer、async属性或者异步加载
- 由于JS会阻塞后面的HTML结构解析和渲染,因此将JS放在 上方,而不是放在里面能有效优化页面(对于某些浏览器无效)
本主题从以下几种方式优化JS
1. 合并JS,减少请求数
如下是未修改前的JS请求数
可以看出,红线勾选的那些是那种本主题必定会用到且较小的JS。因此选择将这些JS合并,以减少请求量。
名称 | 大小(KB) | 耗时(MS) |
---|---|---|
jquery | 34 | 22 |
pjax | 13.6 | 24 |
input | 4.2 | 19 |
tocbot | 4.2 | 24 |
vue | 34.7 | 34 |
clipboard | 3.9 | 30 |
lazyload | 1.5 | 31 |
fancybox | 22.6 | 53 |
总计 | 118.7 | 237 |
如上表格可能有所误差。
当合并JS后,大小变为101KB,请求耗时在79MS
可以看出,减少请求数是提升网站响应速度的首选
2. 采用defer或async
defer是html4的特性,async是html的特性,可以加在script标签上,他们都是异步加载的,但两者稍有不同。
属性 | 加载顺序 | 解析时间 | 注意点 |
---|---|---|---|
defer | 顺序进行,异步并行加载 | 在所有元素解析完成之后,DOMContentLoaded事件触发之前完成 | 1. 会按顺序执行 2. 对不涉及DOM的外部js使用 3. 切记是在所有元素解析完成之后执行 |
async | 乱序进行,异步并行加载 | 加载结束之后立马执行 | 1. 无序执行,因此如果有依赖关系不要使用 2. 加载完成即解析 |
整个过程如下图