浏览器端的javascript加载器

  commonJS,定义了一种同步加载脚本的规范。对于浏览器端而言,因为js脚本都是在远端,用同步的方式可能会长时间阻塞线程。因此,浏览器端的js加载器并不会严格按照commonJS来做。seajs作为一个试图遵循commonJS规范的加载器,是在规范的基础上在外面包一层define,来异步加载js,以下是seajs官网的一个例子:

// 所有模块都通过 define 来定义
define(function(require, exports, module) {

  // 通过 require 引入依赖
  var $ = require(‘jquery‘);
  var Spinning = require(‘./spinning‘);

  // 通过 exports 对外提供接口
  exports.doSomething = ...

  // 或者通过 module.exports 提供整个接口
  module.exports = ...

});

define为回调提供一个获取模块的函数require、两个提供对外接口的对象exports和module。可以看到,模块的依赖是通过调用require来声明的。seajs会用正则把依赖的模块抓取出来,进行加载。为了正确的抓取,seajs定义了一些书写规范。定义模块之后,使用seajs.use使用定义的模块。

  requirejs作为一个遵循AMD规范的加载器。其在全局内定义了两个变量,define和require。可以用以下方式定义一个模块:

define(‘module‘,["alpha"], function (alpha) {
       return {
         verb: function(){
           return alpha.verb() + 2;
         }
       };
   });

同样也可以用类似seajs那样的定义方式。requirejs用以下方式引用一个模块:

require([‘module‘],function(module){
    console.log(module);
}) ;

  对于seajs和requirejs,一个js文件内只能有一个define函数,也就是说一个js文件对应一个模块。requirejs会在加载完一个模块后,马上执行。而seajs会在加载完执行require时执行模块。

  seajs和requirejs还有一些不同。requirejs有shim机制去支持那些不符合AMD规范的模块,seajs本来没有shim机制,之后又加上,最新版又删除了这个功能。requirejs支持webworker,seajs需要第三方的插件支持。

  如果需要实现一个加载器,最需要处理的是模块之间的触发关系。一个模块如果依赖别的模块,就需要等到依赖的模块都准备好了,该模块才处于可用的状态。依赖的模块也有可能有其所依赖的模块。所以需要建立一个触发的机制,让模块在已准备的状态下触发对其依赖的模块,使其检查自身的依赖模块是否都已准备好。seajs和requirejs对这个的实现方式有所不同。这里是我实现的一个版本:github地址

  

时间: 2024-11-04 19:32:34

浏览器端的javascript加载器的相关文章

SeaJS:一个适用于 Web 浏览器端的模块加载器

什么是SeaJS?SeaJS是一款适用于Web浏览器端的模块加载器,它同时又与Node兼容.在SeaJS的世界里,一个文件就是一个模块,所有模块都遵循CMD(Common Module Definition)规范.SeaJS本身遵循(Keep it Simple, Stupid)理念开发,API仅有几个. 为什么用SeaJS?假如我们要开发一个web应用App,在这个应用中需要使用jquery框架.App的首页index.html会用到module1.js,module1.js依赖module2

从易到难,写一个JavaScript加载器之一

先上代码: 1 (function(global) { 2 var createScript, insertScript, makeLoadQueue; 3 createScript = function(src) { 4 var script; 5 script = document.createElement('SCRIPT'); 6 script.src = "" + src + ".js"; 7 return script; 8 }; 9 insertScr

JavaScript AMD 模块加载器原理与实现

关于前端模块化,玉伯在其博文 前端模块化开发的价值 中有论述,有兴趣的同学可以去阅读一下. 1. 模块加载器 模块加载器目前比较流行的有 Requirejs 和 Seajs.前者遵循 AMD规范,后者遵循 CMD规范.前者的规范产出比较适合于浏览器异步环境的习惯,后者的规范产出对于写过 nodejs 的同学来说是比较爽的.关于两者的比较,有兴趣的同学请参看玉伯在知乎的回答 AMD和CMD的区别有哪些.本文希望能按照 AMD 规范来简单实现自己的一个模块加载器,以此来搞清楚模块加载器的工作原理.

使用js加载器动态加载外部Javascript文件

今天在网上找到了一个可以动态加载js文件的js加载器,具体代码如下: JsLoader.js 1 var MiniSite=new Object(); 2 /** 3 * 判断浏览器 4 */ 5 MiniSite.Browser={ 6 ie:/msie/.test(window.navigator.userAgent.toLowerCase()), 7 moz:/gecko/.test(window.navigator.userAgent.toLowerCase()), 8 opera:/o

JavaScript文件加载器LABjs API详解

在<高性能JavaScript>一书中提到了LABjs这个用来加载JavaScript文件的类库,LABjs是Loading And Blocking JavaScript的缩写,顾名思义,加载和阻塞JavaScript,而它的API script()和wait()则优雅地实现了这两个功能,我在高性能JavaScript 加载和执行一文中也简单讲解了这两个核心API的用法.当然,LABjs还有更多的API,本文用实例讲解下LABjs其他API. $LAB.setGlobalDefaults()

Canvas---Canvas图像加载、利用javascript回调机制实现一个图片加载器

canvas的drawImage方法有个缺点,就是当图片还未加载完成时调用它将无效. 当然,在高速运转的游戏主循环中,可以直接忽略这个问题,或者用 img.complete == true来做下判断. 在游戏循环之外的地方,可以用 img.onload = function (){};这样的回调解决. 但是,如果需要实现预先大量图片的加载,并且将加载进度告知用户,这时就需要一个图片加载器. 一.图片加载器原理 1.对于每张图片,开启对应的一个线程去负责加载,加载完成后修改一个变量的值-loade

AMD加载器实现笔记(五)

前几篇文章对AMD规范中的config属性几乎全部支持了,这一节主要是进一步完善.到目前为止我们的加载器还无法处理环形依赖的问题,这一节就是解决环形依赖. 所谓环形依赖,指的是模块A的所有依赖项的依赖中有没有依赖A模块本身的模块.如果有那就说明存在环形依赖.所以检验的方式是利用递归,检查一个模块的依赖的依赖项中有没有依赖A模块,以及依赖项的依赖项的依赖项中有没有A模块,核心代码如下: function checkCircleRef(start, target){ var m = modules[

AMD加载器实现笔记(二)

AMD加载器实现笔记(一)中,我们实现了一个简易的模块加载器.但到目前为止这个加载器还并不能称为AMD加载器,原因很简单,我们还不支持AMD规范中的config配置.这篇文章中我们来添加对config的中baseUrl和packages的支持.API设计如下: 1 require.config({ 2 baseUrl: "./", 3 packages: [{ 4 name: "more", 5 location: "./more" 6 }, {

AMD加载器实现笔记(四)

继续这一系列的内容,到目前为止除了AMD规范中config的map.config参数外,我们已经全部支持其他属性了.这一篇文章中,我们来为增加对map的支持.同样问题,想要增加map的支持首先要知道map的语义. 主要用于解决在两个不同模块集中使用一个模块的不同版本,并且保证两个模块集的交互没有冲突. 假设磁盘有如下文件: 当'some/newmodule'请求'foo'模块时,它将从foo1.2.js总得到'foo1.2'模块:当'some/oldmodule'请求'foo'模块时它将从foo