异步JavaScript加载器
PUBLISHED
简介
异步JavaScript加载提供了一种异步加载JavaScript文件的机制。 它有助于提高web应用/浏览器的性能。 除了这一点,它也提供了一种封装许多不同文件中JavaScript文件的方法,这类似于Java中为实现同样目的而使用的诸如import,package和class关键字。 使用传统的同步加载文件的方法,可能会影响有更多的依赖关系(在运行时负载多个JavaScript文件)的应用程序的性能和可用性。
为此,有多个库可以使用。 在定义模块时,这些库并未遵循异步模块定义(AMD)规范。 让我们来讨论一下这些提高异步加载性能的常用库。
同步与异步
HTML页面中,加载JavaScript模块的传统方法是使用<script>元素,加载css文件时,使用<link>元素。 这种处理方式会强制浏览器在不知道它们以来关系的情况下顺序(假定所有的文件已经按照顺序放置)的执行它们。 如果这些文件之间不存在依赖关系,那么按照顺序执行它们是没有问题的。 同样的,它们也可以并行地执行。 这里谈到异步加载的一部分,可能的话,异步加载器都会并行加载JavaScript文件,从而提高效率。 所以,当减少了页面加载多个文件的时间时,便增强了性能。
AMD(异步模块定义)
AMD - 异步模块定义,开发人员编写JavaScript模块时经常使用该标准,按照该标准写出来的模块可以被任何的AMD-非兼容(AMD-complaint)加载器加载。 常用的AMD API包括require(), define(), exports 和 module. require() 函数在执行一组代码之前,加载一系列从属模块/资源。 该代码被放置在一个回调函数中,只有在所有的依赖被加载之后,该回调函数才会以一个单独线程的方式执行。 define() 函数用于和加载器之间交互脚本已加载的模块列表。
Curl.js
Curl.js是一款小巧快速的AMD-非兼容异步加载器。 大多数异步加载器不能在本地文件系统加载,也就是说,你不能按照“file:”协议使用它们,相反,你应该从Web服务器使用他们。 在同样的思路,你必须“http:"或者"https:"协议从Web服务器上加载一个页面来使用curl。
定义模块
define(['dp1', 'dp2', 'dp3' /* etc */], factory); define(['dp1', 'dp2', 'dp3' /* etc */], module); define(module); define(name, ['dp1', 'dp2', 'dp3' /* etc */], factory); define(name, ['dp1', 'dp2', 'dp3' /* etc */], module); define(name, module);
- [‘dp1’, ‘dp2’, ..]: 模块名。 依赖关系可能会被命名为“require”,“exports”或“module。
- Factory: 定义模块。 以来关系可以作为参数传递给factory。
- Module: 一个JavaScript对象,函数,构造函数,或原始
- ame: 用于命名模块的字符串(不常用/推荐)。
一个典型的AMD封装的CommonJS格式的模块定义。 当定义factory函数,其参数没有依赖关系列表时,便假定了这种格式。 参数“exports”和“module”是可选的。
define(function (require, exports, module) { var dep1 = require('app/foo'); exports.foo2 = function () { return foo() + 2; }; });
另一种使用”pseudo-modules“定义模块的方法
define(['require', 'exports', 'module'], function (require, exports, module) { var dep1 = require('app/foo'); exports.foo2 = function () { return foo() + 2; }; });
Script.js
script.js是一个异步的JavaScript加载器,该加载器具有令人惊讶的,可标记的,轻便的足迹。 像其他的JavaScript加载器,它从任何URL按需加载脚本,而不会阻塞加载其他资源。 传统的加载JavaScript文件的方法
<script src="jquery.js"></script> <script src="some-jquery-plugin.js"></script> <script src="script-that-uses-plugin.js"></script>
使用script.js
//同时加载jQuery和plugin,并给它一个名字“bundle”
$script(['jquery.js', 'some-jquery-plugin.js'], 'bundle') $script('script-that-uses-plugin.js') // in some-jquery-plugin.js $script.ready('bundle', function() { // both jquery & the current plugin are ready // plugin code... }) // in script-that-uses-plugin.js $script.ready('bundle', function() { // use your plugin })
使用script.js的其他方式
$script(['jquery.js', 'some-jquery-plugin.js'], function() { // both jquery & the current plugin are ready })
当工作在较大的路径时,建议定义一个路径变量作为基础。 您可以使用如下方法实现
$script.path('/js/modules/') $script(['dom', 'event'], function () { // use dom & event }) $script.get('http://somedomain.com/base.js', function () { })
Require.js
Require.js是另一种流行的JavaScript文件和模块加载器。 它可以在jQuery,Rhino和Node等JavaScript环境中使用。 它鼓励使用模块lds,而不是脚本标记来模块化代码。 Require.js采用了特殊的属性data-main来启动脚本加载。
// This sets the baseUrl to the "scripts" directory, and // loads a script that will have a module ID of 'main' <script data-main="scripts/main.js" src="scripts/require.js"></script>
在一般情况下,为模块ID设置路径时,建议使用baseURLs +路径配置(path config)。 读取模块时,Require.js会自动添加.js扩展名,所以我们不需要手动添加.js扩展名。
requirejs.config({ //By default load any module IDs from js/lib baseUrl: 'js/lib', //except, if the module ID starts with "app", //load it from the js/app directory. paths //config is relative to the baseUrl, and //never includes a ".js" extension since //the paths config could be for a directory. paths: { app: '../app' } }); // Start the main app logic. requirejs(['jquery', 'canvas', 'app/sub'], function ($, canvas, sub) { //jQuery, canvas and the app/sub module are all //loaded and can be used here now. });
模块和函数
用一对简单的名称/值,定义一个无依赖关系的模块。
define({ color: "black", size: "unisize" });
定义一个有依赖关系的函数。
//module in the same directory as current file define(["./cart", "./list "], function(cart, inventory) { //return an object to define the current module. return { color: "cyan", size: "medium", addToCart: function() { list.decrement(this); cart.add(this); } } } );
定义一个带有简化CommonJS封装器的模块
define(function(require, exports, module) { var a = require('a'), b = require('b'); //Return the module value return function () {}; } );
定义一个带有名称的模块
// module name "foo/title" define("foo/title", ["my/cart", "my/list"], function(cart, inventory) { //Definition of foo/title object. } );
参考: