【译】延迟加载JavaScript
看到一个微信面试题引发的血案 --[译] 什么阻塞了 DOM?中提到的一篇文章,于是决定看下其博客内容,同时翻译下来留作笔记,因英文有限,如有不足之处,欢迎指出。同时,请给它五分钟。
原文地址:https://varvy.com/pagespeed/defer-loading-javascript.html
作者:Patrick Sexton
如何延迟加载JavaScript
真正的延迟加载JavaScript意味着:在页面内容已经完全加载完成之后才开始加载或解析JavaScript(这也就是说JavaScript不能影响页面速度或关键渲染路径)。
- 使用“onload”事件来调用外部JavaScript资源
- 外部JavaScript资源不能在页面内容加载完前加载
- 外部JavaScript资源在内容加载完成之后才开始运行并影响页面
解释
网络上的焦点往往是人们为了找到一种解决方案而抓狂,JavaScript的延迟加载便是焦点其中之一。
许多人说”只要使用defer就可以了“、”只要使用async就可以了“,或者说”只要把你的JavaScript放到页面最底部就可以了“,但是这些都没有解决问题 —— 让页面完全加载完成然后(只能在完全加载之后)加载外部JS。这些方式也不会让你通过从Google页面速度工具中获取的”延迟加载JavaScript“ 警告(这一点译者有些疑问,因为我在测试的时候发现上面的三个方法是可以去掉这个警告的)。
这个解决方案将会解答。
调用外部JavaScript文件的脚本
这段代码放到HTML文档的</body>
标签之前(靠近HTML文档底部)。外部脚本的名称为defer.js
。
<script type="text/javascript">
function downloadJSAtOnload() {
var element = document.createElement("script");
element.src = "defer.js";
document.body.appendChild( element );
}
if ( window.addEventListener ) {
window.addEventListener( "load", downloadJSAtOnload, false );
} else if ( window.attachEvent ) {
window.attachEvent( "onload", downloadJSAtOnload );
} else {
window.onload = downloadJSAtOnload;
}
</script>
这段脚本做了什么?
这段代码说等文档完全加载完,然后加载外部文件”defer.js“。
详细说明
- 1、复制上面的代码
- 2、把代码粘贴到你的HTML文档中,
</body>
标签之前 - 3、把
defer.js
改成你外部文件的名字 - 4、确保到你文件的路径是正确的。例如:如果你使用”defer.js“,那么”defer.js“文件必须和你的HTML文件在相同文件夹下
你可以用它来干嘛(或不能干嘛)
这段代码在你的页面还没完全加载完成之前不会加载外链文件。你应该把你的JavaScript分成两组,一组是页面需要加载的,另一组是做页面加载后要做的事情(比如寻找click事件或其他事情)。可以接受等待并且一直到页面加载后才加载的JavaScript应该都被放到一个外部文件中调用。
例如,在该页面中我使用了上述的脚本来延迟加载谷歌统计、Viglink、以及底部的Google plus头像。我没有理由在页面初始时加载这些文件,因为这些文件和我上述的内容是不相关的,是非必须加载的。也许在你的页面上也会有相同类型的东西,你会在展示给你的用户内容之前让用户等待加载这些资源吗?
为什么其他方式不行?
内联、把脚本放到最底部、使用defer
或者async
这些方法都没有完成先让页面加载,然后在加载JS的目标,并且这些方式也确实不通用以及跨浏览器。
为什么这很重要?
这是因为Google把页面的加载速度作为排名的一个因素,也因为用户想要更快的加载页面。这对你的移动端SEO也大有益处。Google是从它被调用时开始到页面初始化加载完成来测量你的页面加载速度。这也意味着你需要让页面的load
事件尽可能快的完成。谷歌根据网页首页加载时间评估你的网页(并且不要忘了,用户正在等待页面加载)。
Google积极的宣传与推荐prioritizing above the fold content(屏幕内容优先)。所以让屏幕外的任何资源(js、css、images等等)放到主要渲染路径之外是值得努力的。如果这会让你的用户开心,让Google开心,何乐而不为呢。
使用示例
我创建了一个页面,点击这里,你会看到,在这里面我用到了上述代码段。
测试示例文件
好吧,为了举例说明,我写了一些测试页面供你测试。每一个页面做了相同的事情,一个纯HTML页面使用了一个脚本,脚本的内容是等待两秒输出”hello world“。你可以测试这些页面并且看到只有一种方式立即展示出了内容(页面加载时间没有包括这两秒的等待)。
关键点
最最关键的点是要尽可能快的把内容呈现给用户。We have not been doing that with how we have treated our javascript.用户必须要看到他们的内容,因为一些脚本做的事情在可视内容之下。不管你的页面底部有多酷,如果用户从不滚动到页面底部,那么你就毫无原因来加载脚本让页面底部变酷。
工具
使用javascript usage tool来测试你的页面中JavaScript是如何使用的。
翻译结束。
补充扩展
1、defer与async
这两个属性都可以页面优化的目的,但有什么不同呢?一个图即可解答:
2、Below the Fold
根据wordstream中的定义:
Below the fold
是指网页中只有滚动才可见的区域。
Above the Fold
指不需滚动页面就可见的内容区域。
一般而言,不需滚动就展示在屏幕中的内容会接受更多的注意力,需要滚动才可见的内容受到较低的关注。fold
观点来自新闻出版业。