requirejs seajs 区别和seajs的区别

今天看啥 热点:
requireJS源码分析,requirejs源码
1. requireJS概念
2. AMD与CMD区别
3. 模块加载器的来历
4. 模块加载器的利弊
5. 模块加载器的使用场景
6. requireJS源码解读
7.心得总结
一、requireJS概述
RequireJS是一款遵循AMD规范协议的JavaScript模拟加载器。
业界常见模块加载器(labjs、requirejs、seajs)
LABjs的核心是LAB(Loading and Blocking):核心价值是性能优化
至于requirejs和seajs区别,知乎上有专门篇幅讲这个
作者玉伯-支付宝淘宝前端类库KISSY、seajs、arale创始人
地址呈上:/question/
二、AMD与CMD区别
1.名词解释
AMD:Asynchronous Modules Definition异步模块定义,提供定义模块及异步加载该模块依赖的机制。
CMD:Common Module Definition 通用模块定义,提供模块定义及按需执行模块
2. 提前执行:提前异步并行加载
优点:尽早执行依赖可以尽早发现错误;缺点:容易产生浪费
3. 延迟执行:延迟按需加载
优点:减少资源浪费 缺点:等待时间长、出错时间延后
2.1 AMD与CMD代码模式
AMD代码模式-运行策略
define(['./a', './b'], function(a, b) { //运行至此,a.js和b.js已经下载完成 a模块和b模块已经执行完,直接可用;
& & a.doing();
& & // 此处省略500行代码
& & b.doing();
CMD代码模式-运行策略
define(function(require, exports, module) {
& & &var a = require(&./a&); //等待a.js下载、执行完
& & &a.doing();
& & &// 此处省略500行代码
& & &var b = require(&./b&); //依赖就近书写
& & &b.doing();
三、模块加载器来历
web2.0的到来,页面的交互越来越强烈,逐渐变成“互联网应用程序”,js代码越来越庞大,越来越复杂,诞生很多库和框架,相互间存在依赖关系和加载顺序要求。面对错综复杂代码,攻城师不堪重负,迫切渴望解放代码各种关系。
3.1模块代码的演变过程
四、模块加载器的利与弊
五、模块加载器的适用场景
requireJS比较适合独立APP型项目,能够做到统一构建的那种
seajs比较适合多个项目团队协议的工程,不能做到统一构建的那种
六、requireJS源码剖析
源码结构体:三部分
1、requireJS基本介绍
2、requireJS加载原理
3、requireJS整体框架流程图
4、requireJS源码解读(举一个define方法)
5、requireJS使用后几个思考
6.0.1 源码第一个部分组织结构
6.0.2 第二部分代码
6.0.3 第三部分代码结构
6.1:基本介绍
中文API参考地址:/
& & &特点:异步加载、模块化、依赖管理
& & &a) 程序入口-脚本引入:&script data-main=&script/test& src=&script/require.js&&&/script&
& & &调试器显示
6.1.1:入口代码执行链路
源码执行链路:
& & &if (isBrowser && !cfg.skipDataMain) { ... } // 这段代码的主要功能是找到绑定的data-main,然后往全局的cfg对象添加base路径和main。
& & &=& eachReverse();
& & &=& define = function(...) { ... };
& & &=& define.amd = { ... };
& & &=& req.exec = function(text) {... }
& & &=&req(cfg);
代码几个细节点:
& & &isBrowser:两个感叹号可以做类型转换-&转换为布尔类型
& & &!!(typeof window !== 'undefined' && typeof navigator !== 'undefine' && window.document)
& & &cfg.skipDataMain:控制是否引用data-main属性数据
6.1.2:定义模块和引用模块
6.1.3:config配置
6.2 requireJS加载原理
1、载入模块
2、通过模块名解析出模块信息,以及计算出URL
3、通过创建SCRIPT的形式把模块加载到页面中。
4、判断被加载的脚本,如果发现它有依赖就去加载依赖模块。如果不依赖其它模块,就直接执行factory方法
5、等所有脚本都被加载完毕就执行加载完成之后的回调函数。
6.3 requireJS整体框架流程图
6.4 requireJS源码解读(举一个define方法)
define函数的作用
1、globalDefQueue只会有可能在define函数处被压入数据;
注:requireJS有两个队列 a)globalDefQueue 全局队列 b) defQueue: newContext闭包
2、调用依赖时候会根据define进行设置将加载好的标签引入键值对应关系;
3、每一个define模块都会维护一个闭包,而且多数时候这个闭包是无法释放的,面对这个问题,一般采用将大项目拆分,避免首次加载过多资源,防止内存占用过渡问题
4、define方法会根据键值改变对应模块的标识值
6.4.1 requireJS源码解读 define函数主结构体
6.4.2 requireJS源码解读 define函数源码
6.5 requireJS使用后的几个问题
1、使用require后页面引入的js两个data-*属性,有什么用
2、data-main是项目的唯一入口,但是怎么进入这个入口,之后又做了什么?
3、require和define里面怎么执行的,如何管理依赖关系?
4、require和define区别是什么?
5、如何异步加载js文件的?
6.5.1 问题1
第一个问题解答:使用require后页面引入的js两个data-*属性,有什么用
data-*:在浏览器中对脚本进行打tag,创建、移除脚本标签用到
6.5.2:data-main入口的具体实现
6.5.3:require和define怎么执行,如何管理依赖关系?
require方法:
1、检查依赖的模块,根据配置文件,获取js文件的实际路径
2、根据js文件实际路径,在dom中插入script节点,并绑定onload事件来获取该模块加载完成的通知。
3、依赖script全部加载完成后,调用回调函数
define方法:
1、每个define模块都会维护一个闭包
2、define几个关键判断点:
a) checkLoadedTimeoutId b) inCheckLoaded c) stillLoading
依赖关系管理:script标签执行onload事件将全局队列的东西载入context.defQueue,根据相关的映射id(由event参数获取),实例化相关模块
6.5.4:require和define的区别
功能区别:
define: 用来定义模块(注册为requirejs中模块)
require:用来加载和使用模块的
实现代码区别:
如果使用require定义模块,不能执行结果返回任何值,这意味着不能使用这个模块到其他模块
6.5.4:如何异步加载js
看一下req.createNode方法
req.createNode = function(config, moduleName, url) {
& & var node = config.xhtml ?
& & & & & document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
& & & & & document.createElement('script');
& & &node.type = config.scriptType || 'text/javascript';
& & &node.charset = 'utf-8';
& & &node.async = // 异步
当node加载完毕后会调用context.onScriptLoad,做了实例化context.Module对象,并暴露给registry供调用
onScriptLoad: function(evt) {
& & &if (evt.type === 'load' ||
& & & & & (readyRegExp.test(evt.currentTarget || evt.srcElement).readyState)) {
& & & & & interactiveScript =
& & & & & // getScriptData()找evt对应的script,提取data-requiremodule的mod名称
& & & & & var data = getScriptData(evt);
& & & & & pleteLoad(data.id);
1、学习一个工具,先用熟练,之后开始思考是怎么实现
2、框架学习有助于学习大牛的代码组织、编码风格、设计思想,对提升帮助很大(就是内功修炼)
3、看源码大概流程 源码如何组织-&debug理清调用链-&参考别人分析-&demo校验-&总结
相关搜索:
相关阅读:
相关频道:
&&&&&&&&&&&&&&&&&&
WEB前端教程最近更新requirejs和seajs的区别_百度知道
requirejs和seajs的区别
我有更好的答案
  两者的区别如下:
  定位有差异。RequireJS 想成为浏览器端的模块加载器,同时也想成为 Rhino / Node 等环境的模块加载器。SeaJS 则专注于 Web 浏览器端,同时通过 Node 扩展的方式可以很方便跑在 Node 服务器端。
  遵循的规范不同。RequireJS 遵循的是 AMD(异步模块定义)规范,SeaJS 遵循的是 CMD (通用模块定义)规范。规范的不同,导致了两者 API 的不同。SeaJS 更简洁优雅,更贴近 CommonJS Modules/1.1 和 Node Modules 规范。
  社区理念有差异。RequireJS 在尝试让第三方类库修改自身来支持 RequireJS,目前只有少数社区采纳。SeaJS 不强推,采用自主封装的方式来“海纳百川”,目前已有较成熟的封装策略。
  代码质量有差异。RequireJS 是没有明显的 bug,SeaJS 是明显没有 bug。
...
  两者的区别如下:
  定位有差异。RequireJS 想成为浏览器端的模块加载器,同时也想成为 Rhino / Node 等环境的模块加载器。SeaJS 则专注于 Web 浏览器端,同时通过 Node 扩展的方式可以很方便跑在 Node 服务器端。
  遵循的规范不同。RequireJS 遵循的是 AMD(异步模块定义)规范,SeaJS 遵循的是 CMD (通用模块定义)规范。规范的不同,导致了两者 API 的不同。SeaJS 更简洁优雅,更贴近 CommonJS Modules/1.1 和 Node Modules 规范。
  社区理念有差异。RequireJS 在尝试让第三方类库修改自身来支持 RequireJS,目前只有少数社区采纳。SeaJS 不强推,采用自主封装的方式来“海纳百川”,目前已有较成熟的封装策略。
  代码质量有差异。RequireJS 是没有明显的 bug,SeaJS 是明显没有...
其他类似问题
为您推荐:
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁seajs,requirejs是什么,他们的原理是什么?_问答_ThinkSAAS
seajs,requirejs是什么,他们的原理是什么?
seajs,requirejs是什么,他们的原理是什么?
SeaJS是一个遵循CommonJS规范的JavaScript模块加载框架,可以实现JavaScript的模块化开发及加载机制。用来解决目前JavaScript变成中普遍存在的依赖关系混乱和代码纠缠等问题,方便代码的编写和维护。这样说可以吗?
按投票排序
0支持&&/&&0反对
slidejs 没有用常规的clone dom来做滚动。
主要的方法是用绝对定位,重点在最后一张图滚动完成时触发了complete事件,瞬间改变了最后一张图和第一张图的绝对定位,然后又恢复了第一张的位置,欺骗了你的眼睛,从而达到效果。
0支持&&/&&0反对
SeaJS是玉伯写的基于CMD规范的模块加载器,具体实现方案比较trick,比如要对回调函数做静态分析之类的。
Requirejs则是基于AMD规范,相应的原理还是很容易想象出来的,自己写一个简单的AMD加载器就知道了。
PHP开发框架
服务器环境
ThinkSAAS商业授权:
ThinkSAAS为用户提供有偿个性定制开发服务
ThinkSAAS将为商业授权用户提供二次开发指导和技术支持
手机客户端
ThinkSAAS接收任何功能的Iphone(IOS)和Android手机的客户端定制开发服务
官方1群:【已满】
让ThinkSAAS更好,把建议拿来。您所在的位置: &
JavaScript 模块化及 SeaJs 源码分析
JavaScript 模块化及 SeaJs 源码分析
和后端(比如Java)比较就可以看出明显的差距。2009年Ryan Dahl创建了node.js项目,将JavaScript用于服务器编程,这标志“JS模块化编程”正式诞生。
网页的结构越来越复杂,简直可以看做一个简单APP,如果还像以前那样把所有的代码都放到一个文件里面会有一些问题:
全局变量互相影响
JavaScript文件变大,影响加载速度
结构混乱、很难维护
和后端(比如Java)比较就可以看出明显的差距。2009年Ryan Dahl创建了node.js项目,将JavaScript用于服务器编程,这标志&JS模块化编程&正式诞生。
模块就是一些功能的集合,那么可以将一个大文件分割成一些小文件,在各个文件中定义不同的功能,然后在HTML中引入:
var&module1&=&new&Object({&&&&&_count&:&0,&&&&&m1&:&function&(){&&&&&&&&&&&&&&},&&&&&m2&:&function&(){&&&&&&&&&&&&&&}&});&
这样做的坏处是:把模块中所有的成员都暴露了!我们知道函数的本地变量是没法从外面进行访问的,那么可以用立即执行函数来优化:
var&module1&=&(function(){&&&&&var&_count&=&0;&&&&&var&m1&=&function(){&&&&&&&&&&&&&&};&&&&&var&m2&=&function(){&&&&&&&&&&&&&&};&&&&&return&{&&&&&&&&&m1&:&m1,&m2&:&m2&&&&&};&})();&
大家定义模块的方式可能五花八门,如果都能按照一定的规范来,那好处会非常大:可以互相引用!
在node.js中定义math.js模块如下:
function&add(a,&b){&&&&&return&a&+&b;&}&exports.add&=&&
在其他模块中使用的时候使用全局require函数加载即可:
var&math&=&require('math');&math.add(2,3);&
在服务器上同步require是没有问题的,但是浏览器在网络环境就不能这么玩了,于是有了异步的:
require(['math'],&function&(math)&{&&&&&math.add(2,&3);&});&
模块的定义方式如下(模块可以依赖其他的模块):
define(function&(){&&&&&&var&add&=&function&(x,y){&&&&&&&&&return&x+y;&&&&&};&&&&&return&{&add:&add&};&});&
用RequireJS可以加载很多其他资源(看),很好很强大!在工作中用的比较多的是,所使用的规范称为CMD,推崇(应该是指异步模式):
as lazy as possible!
对于依赖的模块的处理方式和AMD的区别在于:
AMD是提前执行(依赖前置),CMD是延迟执行(依赖就近)。
在CMD中定义模块的方式如下:
define(function(require,&exports,&module)&{&&&&&var&a&=&require('./a');&&&&&a.doSomething();&&&&&var&b&=&require('./b');&&&&&b.doSomething();&});&
使用方式直接看,这里就不赘述了!
SeaJS源码分析
刚接触模块化的时候感觉这个太简单了,不就是:
创建script标签的时候设置一下onload和src!
事实上是这样的,但也不完全是!下面来开始看SeaJS的代码()。一个模块在加载的过程中可能经历下面几种状态:
var&STATUS&=&Module.STATUS&=&{&&&&&&&&&&FETCHING:&1,&&&&&&&&&&SAVED:&2,&&&&&&&&&&LOADING:&3,&&&&&&&&&&LOADED:&4,&&&&&&&&&&EXECUTING:&5,&&&&&&&&&&EXECUTED:&6,&&&&&&&&&&ERROR:&7&}&
内存中用Modul对象来维护模块的信息:
function&Module(uri,&deps)&{&&&&&this.uri&=&uri&&&&&this.dependencies&=&deps&||&[]&&&&&&this.deps&=&{}&&&&&&this.status&=&0&&&&&&this._entry&=&[]&&}&
在页面上启动模块系统需要使用seajs.use方法:
seajs.use(&./main&,&function(main)&{&&&&&main.init();&});&
加载过程的整体逻辑可以在Module.prototype.load中看到:
Module.prototype.load&=&function()&{&&&&&var&mod&=&this&&&&&if&(mod.status&&=&STATUS.LOADING)&{&&&&&&&&&return&&&&&}&&&&&mod.status&=&STATUS.LOADING&&&&&var&uris&=&mod.resolve()&&&&&&emit(&load&,&uris)&&&&&for&(var&i&=&0,&len&=&uris.&i&&&&i++)&{&&&&&&&&&mod.deps[mod.dependencies[i]]&=&Module.get(uris[i])&&&&&}&&&&&mod.pass();&&&&&&if&(mod._entry.length)&{&&&&&&&&&mod.onload()&&&&&&&&&return&&&&&}&&&&&var&requestCache&=&{};&&&&&var&m;&&&&&&&&&&for&(i&=&0;&i&&&&i++)&{&&&&&&&&&m&=&cachedMods[uris[i]]&&&&&&&&&if&(m.status&&&STATUS.FETCHING)&{&&&&&&&&&&&&&m.fetch(requestCache)&&&&&&&&&}&else&if&(m.status&===&STATUS.SAVED)&{&&&&&&&&&&&&&m.load()&&&&&&&&&}&&&&&}&&&&&for&(var&requestUri&in&requestCache)&{&&&&&&&&&if&(requestCache.hasOwnProperty(requestUri))&{&&&&&&&&&&&&&requestCache[requestUri]()&&&&&&&&&}&&&&&}&}&
总体上逻辑很顺就不讲了,唯一比较绕的就是_entry数组了。网上没有找到比较通俗易懂的文章,于是看着代码连蒙带猜地大概看懂了,其实只要记住它的目标即可:
当依赖的所有模块加载完成后执行回调函数!
换种说法:
数组_entry中保存了当前模块加载完成之后、哪些模块的依赖可能加载完成的列表(依赖的反向关系)!
举个例子,模块A依赖于模块B、C、D,那么经过pass之后的状态如下:
498)this.width=498;' onmousewheel = 'javascript:return big(this)' alt="" src="/wyfs02/M00/76/61/wKioL1ZScjLDy-L_AAAK83TxN30801.png" />
此时A中的remain为3,也就是说它还有三个依赖的模块没有加载完成!而如果模块B依赖模块E、F,那么在它load的时候会将A也传递出去:
498)this.width=498;' onmousewheel = 'javascript:return big(this)' alt="" src="/wyfs02/M01/76/61/wKioL1ZScjLwSfb9AAASMj2DOzQ096.png" />
有几个细节:
已经加载完成的模块不会被传播;
已经传播过一次的模块不会再次传播;
如果依赖的模块正在加载那么会递归传播;
维护好依赖关系之后就可以通过Module.prototype.fetch来加载模块,有两种sendRequest的实现方式:
importScripts
然后根据结果执行load或者error方法。依赖的所有模块都加载完成后就会执行onload方法:
Module.prototype.onload&=&function()&{&&&&&var&mod&=&this&&&&&mod.status&=&STATUS.LOADED&&&&&for&(var&i&=&0,&len&=&(mod._entry&||&[]).&i&&&&i++)&{&&&&&&&&&var&entry&=&mod._entry[i]&&&&&&&&&if&(--entry.remain&===&0)&{&&&&&&&&&&&&&entry.callback()&&&&&&&&&}&&&&&}&&&&&delete&mod._entry&}&
其中--entry.remain就相当于告诉entry对应的模块:你的依赖列表里面已经有一个完成了!而entry.remain === 0则说明它所依赖的所有的模块都已经加载完成了!那么此时将执行回调函数:
for&(var&i&=&0,&len&=&uris.&i&&&&i++)&{&&&&&exports[i]&=&cachedMods[uris[i]].exec();&}&if&(callback)&{&&&&&callback.apply(global,&exports)&}&
脚本下载完成之后会马上执行define方法来维护模块的信息:
没有显式地指定dependencies时会用parseDependencies来用正则匹配方法中的require()片段(指定依赖列表是个好习惯)。
接着执行factory方法来生成模块的数据:
var&exports&=&isFunction(factory)&?&&&&&factory.call(mod.exports&=&{},&require,&mod.exports,&mod)&:&&&&&factory&
然后执行你在seajs.use中定义的callback方法:
if&(callback)&{&&&&&callback.apply(global,&exports)&}&
当你写的模块代码中require时,每次都会执行factory方法:
function&require(id)&{&&&&&var&m&=&mod.deps[id]&||&Module.get(require.resolve(id))&&&&&if&(m.status&==&STATUS.ERROR)&{&&&&&&&&&throw&new&Error('module&was&broken:&'&+&m.uri)&&&&&}&&&&&return&m.exec()&}&
到这里核心的逻辑基本上讲完了,补一张状态的转换图:
498)this.width=498;' onmousewheel = 'javascript:return big(this)' alt="" src="/wyfs02/M02/76/63/wKiom1ZScdizSAA5AAAo_vFvjyU304.png" />
以后在用的时候就可以解释一些诡异的问题了!
模块化非常好用,因此在ECMAScript 6中也开始支持,但是浏览器支持还是比较堪忧的~~【编辑推荐】【责任编辑: TEL:(010)】
关于&&&&的更多文章
计算机语言在保质期方面有着与众不同的独特规律。其中最为热门的
所以姑娘,让我们做一枚花见花开的程序媛。
讲师: 0人学习过讲师: 10人学习过讲师: 3人学习过
Java 8版本最大的改进就是Lambda表达式,其目的是使Ja
美国旧金山时间3月31日,在红木城Oracle公司总部,Ora
从2006年12月份Sun发布Java 6后,经过五年多的不懈努
本书采用“如何解决问题”的方式阐述Ruby编程,涵盖了以下内容:Ruby术语和基本原理;数字、字符串等低级数据类型的操作;正则表
51CTO旗下网站

我要回帖

更多关于 requirejs seajs 区别 的文章

 

随机推荐