requirejs:性能优化之及早并行加载

发布于 2021-08-11 16:19:49 字数 6266 浏览 1388 评论 0

为了提高页面的性能,通常情况下,我们希望资源尽可能地早地并行加载。这里有两个要点,首先是尽早,其次是并行。

通过data-main方式加载要尽可能地避免,因为它让requirejs、业务代码不必要地串行起来。下面就讲下如何尽可能地利用浏览器并行加载的能力来提高性能。

低效串行:想爱但却无力

最简单的优化,下面的例子中,通过两个并排的script标签加载require.js、main.js,这就达到了require.js、main.js并行加载的目的。

但这会有个问题,假设main.js依赖了jquery.js、anonymous.js(如下代码所示),那么,只有等main.js加载完成,其依赖模块才会开始加载。这显然不够理想,后面我们会讲到如何避免这种情况,下面是简单的源码以及效果示意图。

demo.html

<!DOCTYPE html>
<html>
<head></head>
<body>
<h1>main.js、anynomous.js串行加载</h1>

<script type="text/javascript" src="js/require.js"></script>
<script type="text/javascript" src="js/main.js"></script>

</body>
</html>

js/main.js:

require(['js/anonymous'], function(Anonymous) {
  alert('加载成功');
});

js/anonymous.js:

define(['js/jquery'], function() {
  console.log('匿名模块,require直接报错了。。。');
  return{
    say: function(msg){
      console.log(msg);
    }
  }
});

最终效果:

简单匿名:一条走不通的路

正常情况下,假设页面里有如下几个<script>标签,现代浏览器就会并发请求文件,并顺序执行。但在requirejs里,如果这样做的话,可能会遇到一些意料之外的情况。如下所示,四个并排的标签,依次请求了require.jsjquery.jsanonymous.jsmain.js

demo.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>demo</title>
</head>
<body>
<h1>requirejs并行加载例子</h1>

<script type="text/javascript" src="js/require.js"></script>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/anonymous.js"></script>
<script type="text/javascript" src="js/main.js"></script>

</body>
</html>

预期中,资源会并行加载,但实际上,你会在控制台里看到下面的错误日志。

为什么呢?对于requirejs来说,上面的js/anonymous.js是一个匿名的模块,requirejs对它一无所知。当你在main中告诉requirejs说我要用到js/anonymous这个模块时,它就傻眼了。所以,这里就直接给你报个错误提个醒:不要这样写,我不买账。

那么,及早并行加载的路是否走不通了呢?未必,请继续往下看。

答案就在身边:注册为命名模块的jquery

简单改下上面的例子,比如这样,然后。。它就行了。。

<script type="text/javascript" src="js/require.js"></script>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/main.js"></script>

原因很简单。因为jquery把自己注册成了命名模块。requirejs于是就认得jquery了。

if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
  define( "jquery", [], function () { return jQuery; } );
}

jquery的启发:起个好名字很重要

上面我们看到,给模块起个名字,将匿名模块改成命名模块(named module),就开启了我们的并行加载之旅。从这点看来,起名字真的很重要。

那么我们对之前的例子进行简单的改造。这里用了个小技巧,利用命名模块js/name-module.js来加载之前的匿名模块js/anonymous.js。可以看到,requirejs不报错了,requirejs跟name-module.js也并行加载了。

demo.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">

<title>demo</title>
</head>
<body>
<h1>并行加载requirejs、jquery</h1>

<script type="text/javascript" src="js/require.js"></script>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/name-module.js"></script>
<script type="text/javascript" src="js/main.js"></script>

</body>
</html>

js/name-module.js

define('name-module', 'js/anonymous', [], function() {
  return {
    say: function(msg){
      alert(msg);
    }
  };
});

最终效果图:

通往希望之门:解决anonymous模块的串行问题

如果你能耐着性子看到这一节,说明少年你已经发现了上一节很明显的一个问题:尽管name-module.js并行加载了,但anonymou.js其实还是串行加载,那做这个优化还有什么意义?

没错,如果最终优化效果这样的话,那是完全无法接受的。不卖关子,这个时候就要请出我们的requirejs打包神器r.js。通过打包优化,将anonymous.jsname-module.js打包生成一个文件,就解决了串行的问题。

1、安装打包工具

npm install -g requirejs

2、创建打包配置文件,注意,由于jquery.js比较通用,一般情况下会单独加载,所以从打包的列表里排除

{
  "appDir": "./",  // 应用根路径
  "baseUrl": "./",  // 
  "dir": "dist",  // 打包的文件生成到哪个目录
  "optimize": "none", // 是否压缩
  "modules": [
    {
      "name": "js/name-module",
      "exclude": [
        "jquery"  // 将jqury从打包规则里排除
      ]
    }
  ]
}

3、运行如下命令打包

r.js -o ./build.js 

4、打包后的 name-module,可以看到,匿名模块也被打包进去,同时被转换成了命名模块

define('js/anonymous',['jquery'], function() {
  console.log('匿名模块,require直接报错了。。。');
  return{
    say: function(msg){
      console.log('anonymous: '+msg);
    }
  }
});
define('js/name-module', ['js/anonymous'], function() {
  return {
    say: function(msg){
      alert('name module: '+msg);
    }
  };
});

5、再次访问 demo.html,很好,就是我们想要的结果

写在后面

上面主要提供了及早并行加载的思路,但在实际利用 requirejs 打包的过程中,还会遇到一些需要小心处理的细节问题,当然也有一些坑。后面有时间再总结一下。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

0 文章
0 评论
84960 人气
更多

推荐作者

烙印

文章 0 评论 0

singlesman

文章 0 评论 0

独孤求败

文章 0 评论 0

晨钟暮鼓

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文