相信很多与页面打过交道的同学都对 Yahoo 的 Best Practices for Speeding Up Your Web Site 不陌生。而这 35 条最佳实践中,对 Javascript 的加载顺序的要求是:Put Scripts at the Bottom。因为根据 HTTP/1.1 specification 看来,在同一时间加载两个文件是最理想的,而 Javascript 脚本会阻碍平行下载。Steve 说那是 2008 – 2009 那个时代用的。现在,加载 Javascript 已经有了革命性的化变。

加载 Javascript 最佳实践

在开讲之前,有一个必须解决的问题是:为什么我们要把 JS 文件放在 </body> 之前的最底部。根本原因是,它不能平行下载。而其实并不是所有浏览器都不支持。现在大部分浏览器都支持 Script 的平行下载,除了老掉牙的 IE6&7、Firefox 2&3.0、 Safari 3、Chrome 1。但我们最熟悉的老掉牙同学 IE6 (或以IE为核的那些壳)还是中国(甚至世界上)市场上占用率最高的浏览器,因此我们需要一个折衷的方案。

一、分析

我们有6种方法可以实现平行(NON-Blocking)下载:

  • XHR Eval – 用 XHR 下载,并 eval() 执行 responseText.。
  • XHR Injection – 用 XHR 下载,在页面中动态创建一个 script 元素,并将 responseText 作为其 text 。
  • Script in Iframe – 把脚本放在 HTML 中,使用 ifame  来下载它。
  • Script DOM Element – 动态创建一个 script 元素,把 src 指向脚本URL.
  • Script Defer – 给 script 标添加 defer 属性
  • document.write Script Tag – 利用 document.write <script src="/UploadFiles/2021-04-02/"> 添加到 HTML 中。但这个只对 IE 有效。

兼容性可看下图:

Technique Parallel Downloads Differ Existing Scripts Busy Indicators Ensures Order Size (bytes) XHR Eval IE, FF, Saf, Chr, Op no no Saf, Chr - ~500 XHR Injection IE, FF, Saf, Chr, Op no yes Saf, Chr - ~500 Script in Iframe IE, FF, Saf, Chr, Op no no IE, FF, Saf, Chr - ~50 Script DOM Element IE, FF, Saf, Chr, Op yes yes FF, Saf, Chr FF, Op ~200 Script Defer IE, Saf4, Chr2, FF3.1 yes yes IE, FF, Saf, Chr, Op IE, FF, Saf, Chr, Op ~50 document.write Script Tag IE, Saf4, Chr2, Op yes yes IE, FF, Saf, Chr, Op IE, FF, Saf, Chr, Op ~100

二、方案

对于究竟应该使用哪种方案。这完全取决于你需要自身的需要。这张图描述了什么时候使用什么方法:

加载 Javascript 最佳实践

从总体上看来,Script DOM Element 是比较好的方案。NCZ 的博客上提过,目前最好的技术是:

  1. 创建两个 JavaScript  文件。第一个文件只提供动态下载 Javascript 的代码,第二个文件则包含所有其他页面所需脚本的文件。
  2. <script> 在页部(</body> 之前)引入第一个文件。
  3. 创建第二个 <script> 来执行下载第二个 Javascript 文件的函数和其他的初始化代码。

三、实现代码

根据上面的提到的技术。NCZ 推荐第一个文件只包含相应的实现第二个文件动态加载的代码:
复制代码 代码如下:
function loadScript(url, callback){

var script = document.createElement("script")
script.type = "text/javascript";

if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" ||
script.readyState == "complete"){
script.onreadystatechange = null;
callback();
}
};
} else { //Others
script.onload = function(){
callback();
};
}

script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}

然后,我们可以在页面中这样做:
复制代码 代码如下:
<script type="text/javascript" src="/UploadFiles/2021-04-02/first.js"><script type="text/javascript">
loadScript("http://your.cdn.com/second.js", function(){
//初始化你的代码
});
</script>

在 HTML5 上,我们可以使用 async 属性。这个 HTML 属性的作用正是我们需要的 NON-Blocking 下载技术。虽然目前支持的浏览器并不多(似乎只有 Firefox 3.6+ ?),但给需要平行下载的 Javascript(按照方案看来,一般是第一个 JS 文件) 加上这个属性,也不会影响其他不支持的浏览器,所以,是推荐使用的。
复制代码 代码如下:<script type="text/javascript" async src="/UploadFiles/2021-04-02/foo.js">四、实践
YUI3 的 Loader 使用了 NCZ 的这样的方法。而在支付宝。我们也使用了类似的方法。这里简单说一下。
复制代码 代码如下:
<script type="text/javascript" charset="utf-8">
// 配置 combo 服务的 PATH
araleConfig = {
combo_host: "http://domain.com",
combo_path: '/path/to/the/compressed/file'
}
</script>
<script type="text/javascript" src="/UploadFiles/2021-04-02/core.js">
在使用的时候,再利用 Loader.use() 来实现代码的动态加载。当然,这里不仅仅是动态加载,还有一定的缓存机制在里面。建议你查看相关的 combo 服务的技术。目前支付宝前端架构组的工友们,已经在这一块取得了一些不错的进展(根据测试报告,速度是非常不错的,可能会在适当的时候开源出来)。

五、总结
前端性能优化方面。还有很多东西可以做。并且,随着 HTML5 技术的出现和 Javascript 技术的不断创新,相信还有更多东西是值得期待。前端们,加油吧,未来有很多东西应该是由你来主导的。

Reference:

  1. Loading Scripts Without Blocking
  2. The best way to load external JavaScript
  3. Evolution of Script Loading
  4. What is a non-blocking script?
  5. HTML5 – Scripting: async Attribute
标签:
加载,Javascript

免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
桃源资源网 Design By www.nqtax.com

评论“加载 Javascript 最佳实践”

暂无“加载 Javascript 最佳实践”评论...

《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线

暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。

艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。

《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。