关于雅虎的14条军规。
关于个人对前端性能优化的认识。
主要记载学习笔记。
读书也并不意味着照本宣科,大部分内容都是根据书中理解然后进行知识拓展,也多聊一聊自己对前端性能的理解,所以理解难免有错,如果有错误,希望不吝指正。
规则5:将样式表放在顶部
HTML 标准要求把样式表和JS的内容都放在顶部。js内容暂且不说。
雅虎团队做了一些有趣的测试。他们为了让网页加载的更快,尝试放在文档底部。
但结果,却让用户感觉页面运行的更缓慢了。
逐步呈现
页面通常都是按顺序进行下载的,设计到底部的初衷是想让用户先看到最重要的组建内容,以及页面内容,最后在进行样式渲染。
但是将样式表放在文档底部却会导致浏览器阻止内容的逐步呈现。
当时我看到这句话,脑海中产生一副画面,一个小孩从上面扔东西,一个妇人拿个兜子去挨个接,直到没有力气拿不住了,然后把这些东西直接扔到地上。
在我想来最后的重物就是这个CSS文件了。
产生的影响
白屏
将CSS放到底部会产生短暂的白屏,因为逐步呈现被禁止了。
DEMO.
我记得前几天在segfaultment社区有人提白屏问题。但不是像这种“兜着”的白屏,我觉得他的问题是响应的内容的图片很大,还有些资源找不到。
无样式内容的闪烁
在页面中,文档为样式使用了一个CSS规则,但是却在最后的底部,又引入了一个CSS资源,有进行了页面重绘,所以造成了页面无样式内容的闪烁。
DEMO.
为什么造成这样
如果样式表仍在加载,构建呈现树就是一种浪费,因为在所有样式表加载并解析完毕之前无需绘制任何东西。否则就会遇到无样式内容闪烁的问题。 —DavidHyatt.
其实现在我们工作里,有进行页面加载进来后在利用JS进行位置重绘这样的问题,这样无形中就削弱了性能。
几个DEMO测试
可以对比一下放到底部和顶部的时间。
我这里其实相差不大的,甚至底部还要更快一些,但是白屏的时间让人体验太差了。
底部
顶部
关于import引入
@import 必须放在所有其他规则之前。
可能会出现一些样式引入了但是却没有加载进来让人挠头的问题。
使用@import会让之组建下载的无序性,因为使用@import引用的文件只有在引用它的那个css文件被下载、解析之后,浏览器才会知道还有另外一个css需要下载,这时才去下载,然后下载后开始解析、构建render tree等一系列操作。这种情况就类似于我刚说的,页面加载完后,利用JS去重绘样式,重绘位置。
规则6:将脚本放在底部
JS是一个很霸道的语言。JS运行当中,在解释器运行JS的时候,JS代码没完成之前,其他所有代码全部阻断。
在JS中有一个预处理过程,预处理完了才执行,预处理完了,JS代码从上到下的进行执行。这里涉及到一个变量提升的知识点。
文中尝试把JS放到中部,顶部,底部不同位置来测试产生的影响。
放在中部
下载JS代码需要10S左右的时间,页面上部分(脚本以上)代码立即显示出来了,而下部分要花大约10S才能显示出来,这段时间页面在加载脚本。
逐步呈现
使用脚本时,对于所有位于脚本以下的内容,逐步呈现都被阻塞。将脚本放在页面越靠下的地方,意味着更多的内容能够逐步地呈现。
并行下载和脚本阻塞下载
并行下载意味着我们可以下载更多的组件(取决于你的宽带和CPU速度),但是下载脚本时并行下载还是被禁用了。一部分原因是因为可能你的JS代码有类似document.write的操作,另一个原因为了保证JS脚本是按特定顺序来加载到浏览器中的。(js代码中的互相依赖。)
文中还提到了defer 延时加载,但是在Firfox中延迟脚本也会阻塞呈现和并行加载。
关于defer 和async 多说两句,个人建议不要使用,就打defer而言,官方说HTML中脚本是按顺序执行,但是你可以尝试一下,在页面上使用defer 引入两个相关联的JS脚本, 第一个JS比第二个JS要大,有可能会导致顺序的错乱。
对比
规则7:避免CSS表达式
CSS表达式,你用过吗?
CSS表达式是CSS属性由JS来进行设定的。
这里用expression方法来接受了一个JS表达式,CSS的属性被设置成为对JS表达式值得结果。
更新的频率过于频繁
CSS表达式的问题在于页面对其进行的操作频率非常高,当页面滚动甚至鼠标滑动时都要运行求职。影响了JS性能。
解决方式
解决该问题方式基本都使用JS来完成操作,文中还介绍了可以创建一次性表达来进行替换。
简单介绍一下一次性表达式:
CSS表达式调用了BgColor函数,该函数设定了一个明确的值,并且移除了CSS表达式。
我感觉这就是一种隐性的替换。还不如直接就用JS来操作。
不过多琢磨几下,你们觉得用一次性表达式和用JS来渲染 那个对页面性能更友好呢?
规则8:使用外部Js和Css
平常开发中,如果能复用的我基本单例放一个文件里,不能的就内联写到页面里。来看看书里是怎么讲的。
其实我以前觉得有点规模公司的网站,CSS,JS应该很规范,抱着学习的角度去看看,有的还不及我写的呢~哈哈~~
内联VS 外置
来看看内联与外置的对比。
首次访问时,内联要快一些,二次访问浏览器加了缓存感觉2个速度相差不大。
书中也提到了内联比外部的快的原因因为需要承担多个HTTP请求,在第一条规则里已经提到了。
页面浏览量
用户访问的次数越少,内联的Js和Css更具优势。
空缓存与完整缓存
如果网站本质上能够为用户带来完整缓存率,使用外部文件的收益将更大。如果不大可能使用完整缓存,则内联是更好的选择。
组件重用
如果网站中使用了相同的样式和JS脚本,提高了组件的重用率。那么引入外部文件是一个更好的选择,因为用户在首页进行导航时,JS和CSS文件已经被缓存进来了。
两全其美
内联元素无法使用浏览器缓存,书里提供了两种方法,达到两全其美。
加载后下载
主页画面作为浏览口进行”拉客”,加载后,通过JS方法俩下载其他页面需要的CSS,JS方法。
动态内联
如果主页服务器直到一个组件是否在浏览器的缓存中,就可以在内联和外部之间做出最佳的选择。
书中通过判断cookie值的存在来做对应的选择。
我自己更倾向于第一种方式。
(未完待续)