2010年1月22日星期五

【译】【精品】Javascript载入过程的优化手段

英文原文:http://www.phpied.com/javascript-loading-strategies/

Javascript有一个许多人都不知道的黑暗面。它导致了浏览器停止执行工作指导script被下载,解析和执行。它为什么会导致这个问题呢?

好问题!在我解答之前,我需要解释下浏览器是如何构建一个页面的。浏览器做的第一件事是从服务器接收一个HTML文档来在内存中建立一个DOM对象。当浏览器在将HTML转换成DOM时,它一定会的遇到一些额外依赖的引用,如CSS文档和图像。每当此时,它会向服务器请求那个依赖文档。它不需要等待一个被加载完成后再加载另一个,它会发起尽可能多的请求。这样,页面会一次一个节点的构建并且当依赖下载完成后加载到正确的位置。当遇到Javascript的依赖时一切都被搞糟了!当遭遇Javascript时,浏览器会停止构建BOM并且等待文件下载完毕。一旦接受到之后,它解析并执行它。只有一切完成之后浏览才会继续构建DOM。我怀疑这是为了给脚本提供一个尽可能稳定的DOM。如果在脚本执行的时候DOM还在不停的变化,事情就会变糟了。总之,在浏览器无法构建DOM的这段时间是由script的大小和复杂度决定的。

想象下在<head>里面载入一个200k的Javascript文档。假设这个文档不仅巨大而且计算复杂需要花费一个半秒来完成。那么在这一两秒中内,页面会一直空着知道下载和计算完成。访问者必须要容忍一个半秒的等待。考虑到大部分人不会花费平均每个页面几秒的时间在一个页面上,而且那时一个全部白屏的页面。

Reduce
压缩
如何解决这个问题?方法之一是也所JS文件的大小!现在有很多的压缩JS文件的软件。如JSmin,YUI Compressor等等。

Defer延迟
一旦你确保文件尽可能的小了,下一步呢?让在JS下载时文件页面不是白屏。你可以不将<script>标签放到<head>里面,相反你可以放到<body>里面。<script>标签之前的html会被加载,这样访问者就不会看到白屏了,而会看到<script>标签之前的内容。

Go Async异步方法
另一个方法就是使用异步执行的方法来获取JS脚本。你可以用Javascript来向DOM中插入<script>标签,这样浏览器会异步的获取标签指示的JS文件。唯一难以确定的是你不知道什么时候脚本下载并且解析执行完毕,不过你可以使用回调函数的方法来实现。很多的JS库提供了这种方法。但是如果你想自己完成这些工作,就需要应对浏览器之间的差异性了。

Be Lazy
延迟运算(分为解析与执行)
有的时候你所需要的JS文件并非一定被执行了,如页面导航的JS。如果访问者不使用导航而是直接点击了链接那么它就不需要一开始就解析和执行导航的JS代码。这种情况你就可以不用在导航时直接直接执行,您也可以先下载这些JS代码,然后再执行。当然还有其他方法:http://lifesinger.org/blog/2010/01/the-deferred-evaluation-of-yui3/

Bite Size
上面的方法中你仍旧需要先加载一些核心的JS组件然后才能实现。如果这个核心组件也很庞大但我们只用到了很少的功能,那怎么办?那你可以自己试着提炼出你需要的功能。

没有评论: