【译】延迟加载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观点来自新闻出版业。

【译】延迟加载JavaScript的更多相关文章

  1. 「译」JavaScript 的怪癖 1:隐式类型转换

    原文:JavaScript quirk 1: implicit conversion of values 译文:「译」JavaScript 的怪癖 1:隐式类型转换 译者:justjavac 零:提要 ...

  2. 【译】JavaScript 开发者年度调查报告

    截至目前有超过了 5000 人参与了(该次调查),准确的说是 5350 人.我迫不及待的想要和大家分享一下这次调查的细节.在分享之前我想要感谢参与调查的每一个人.这是 JavaScript 社区一个伟 ...

  3. (译)JavaScript内存泄露

    译者前言 原文地址:Memory leaks 最近简单了解了下JavaScript的闭包和垃圾回收机制(GC),这中间也不得不接触内存泄露这个概念.然后不小心找到了这篇文章,看下来后理解了不少东西,于 ...

  4. [译]理解Javascript的异步等待

    原文链接: https://ponyfoo.com/articles/understanding-javascript-async-await 作者: Nicolás Bevacqua 目前async ...

  5. 【转】【译】JavaScript魔法揭秘--探索当前流行框架中部分功能的处理机制

    推荐语: 今天推荐一篇华为同事的同事翻译的一篇文章,推荐的主要原因是作为一个华为员工居然晚上还能写文章,由不得小钗不佩服!!! 其中的jQuery.angular.react皆是十分优秀的框架,各有特 ...

  6. 【简译】JavaScript闭包导致的闭合变量问题以及解决方法

    本文是翻译此文 预先阅读此文:闭合循环变量时被认为有害的(closing over the loop variable considered harmful) JavaScript也有同样的问题.考虑 ...

  7. 【译】Javascript中的数据类型

    这篇文章通过四种方式获取Javascript中的数据类型:通过隐藏的内置[[Class]]属性:通过typeof运算符:通过instanceof运算符:通过函数Array.isArray().我们也会 ...

  8. (译) 《Javascript 24条最佳实践》

    (摘录) <Javascript 24条最佳实践> 自己一直偏向于实用主义,不是学院派,不是学究派,只讲究把东西能够很好的做出来,但经过一段时间的开发工作当自己总结出来一些东西时,觉得挺有 ...

  9. 【译】JavaScript Promise API

    原文地址:JavaScript Promise API 在 JavaScript 中,同步的代码更容易书写和 debug,但是有时候出于性能考虑,我们会写一些异步的代码(代替同步代码).思考这样一个场 ...

随机推荐

  1. achartengine画出动态折线图

    achartengine画出动态折线图的效果最近有个项目需要用到实时曲线图,我也上网搜索了一下,最后还是选择使用achartengine这个现成的东西,毕竟自己再canvas一下实在是太麻烦,而且项目 ...

  2. 写自己的一个pdo数据库操作框架

    http://stackoverflow.com/questions/20669850/pdo-database-abstraction-layer-with-multiple-queries-in- ...

  3. javascript 中获取对象的长度(map对象的长度)--js关联数组的长度

    var n = {1:100, 2:101, 3:102, 4:103}; 怎么获取这个对象n的长度呢? 方法一: function getLength(obj){ var count = 0; fo ...

  4. BigDecimal 高精度计算 熟悉扩展,java除法保留小数问题

    java保留两位小数问题: 方式一: 四舍五入  double   f   =   111231.5585;  BigDecimal   b   =   new   BigDecimal(f);  d ...

  5. cronolog 对 tomcat 7 进行日志切割

    一.安装 软件 cronolog-1.6.2.tar.gz tar zxvf cronolog-1.6.2.tar.gz cd cronolog-1.6.2 ./configure && ...

  6. (简单) POJ 1426 Find The Multiple,BFS+同余。

    Description Given a positive integer n, write a program to find out a nonzero multiple m of n whose ...

  7. 分治算法(Divide-and-Conquer)和Google的云计算

    1.云计算:涉及到存储.计算.资源的调度和权限的管理等   2.分治算法的原理:           讲一个复杂的问题,分成若干个简单的子问题进行解决,然后对子问题的记过进行合并,得到原有问题的解   ...

  8. 10、手把手教你Extjs5(十)自定义模块的设计

    从这一节开始我们来设计并完成一个自定义模块.我们先来确定一个独立的模块的所能定义的一些模块信息.以下信息只是我自己在开发过程中想到或用到的,希望有新的想法的或者有建议的跟贴回复. 一个独立模块包含以下 ...

  9. python web开发基本概念

    参考了廖雪峰的Python博客. web请求顺序: 浏览器发送一个http请求 服务器收到请求后,生成一个html文档. 服务器将html文档作为http相应的body发送给浏览器 浏览器收到http ...

  10. VS2010 中 error 2732: 链接规范与的早期规范冲突 的解决

    在实验室做项目的时候遇到了这个问题,终于整明白了. 一般来说这个错误出现在类似以下的语句中 extern "C" int yylex(void); extern "C&q ...