RequireJS 入门指南 已翻译 100%

oschina 投递于 2013/08/15 08:58 (共 8 段, 翻译完成于 08-19)
阅读 70199
收藏 177
18
加载中

简介

如今最常用的JavaScript库之一是RequireJS。最近我参与的每个项目,都用到了RequireJS,或者是我向它们推荐了增加RequireJS。在这篇文章中,我将描述RequireJS是什么,以及它的一些基础场景。

异步模块定义(AMD)

谈起RequireJS,你无法绕过提及JavaScript模块是什么,以及AMD是什么。

JavaScript模块只是遵循SRP(Single Responsibility Principle单一职责原则)的代码段,它暴露了一个公开的API。在现今JavaScript开发中,你可以在模块中封装许多功能,而且在大多数项目中,每个模块都有其自己的文件。这使得JavaScript开发者日子有点难过,因为它们需要持续不断的关注模块之间的依赖性,按照一个特定的顺序加载这些模块,否则运行时将会放生错误。

super0555
super0555
翻译于 2013/08/18 20:12
7

当你要加载JavaScript模块时,就会使用script标签。为了加载依赖的模块,你就要先加载被依赖的,之后再加载依赖的。使用script标签时,你需要按照此特定顺序安排它们的加载,而且脚本的加载是同步的。可以使用async和defer关键字使得加载异步,但可能因此在加载过程中丢失加载的顺序。另一个选择是将所有的脚本捆绑打包在一起,但在捆绑的时候你仍然需要把它们按照正确的顺序排序。

AMD就是这样一种对模块的定义,使模块和它的依赖可以被异步的加载,但又按照正确的顺序。

Getting Started with RequireJS Library

CommonJS, 是对通用的JavaScript模式的标准化尝试,它包含有 AMD 定义 ,我建议你在继续本文之前先读一下。在ECMAScript 6这个下一版本JavaScript 规范中,有关于输出,输入以及模块的规范定义,这些将成为JavaScript语言的一部分,而且这不会太久。这也是关于RequireJS我们想说的东西。

super0555
super0555
翻译于 2013/08/18 20:26
4

RequireJS?

RequireJS是一个Javascript 文件和模块框架,可以从 http://requirejs.org/下载,如果你使用Visual Studio也可以通过Nuget获取。它支持浏览器和像node.js之类的服务器环境。使用RequireJS,你可以顺序读取仅需要相关依赖模块。

RequireJS所做的是,在你使用script标签加载你所定义的依赖时,将这些依赖通过head.appendChild()函数来加载他们。当依赖加载以后,RequireJS计算出模块定义的顺序,并按正确的顺序进行调用。这意味着你需要做的仅仅是使用一个“根”来读取你需要的所有功能,然后剩下的事情只需要交给RequireJS就行了。为了正确的使用这些功能,你定义的所有模块都需要使用RequireJS的API,否者它不会像期望的那样工作。

姜鹏飞
姜鹏飞
翻译于 2013/08/16 11:43
6

RequireJS API 存在于RequireJS载入时创建的命名空间requirejs下。其主要API主要是下面三个函数:

  • define– 该函数用户创建模块。每个模块拥有一个唯一的模块ID,它被用于RequireJS的运行时函数,define函数是一个全局函数,不需要使用requirejs命名空间.
  • require– 该函数用于读取依赖。同样它是一个全局函数,不需要使用requirejs命名空间.
  • config– 该函数用于配置RequireJS.

在后面,我们将教你如果使用这些函数,但首先让我们先了解下RequireJS的加载流程。

姜鹏飞
姜鹏飞
翻译于 2013/08/16 12:29
4

data-main属性

当你下载RequireJS之后,你要做的第一件事情就是理解RequireJS是怎么开始工作的。当RequireJS被加载的时候,它会使用data-main属性去搜寻一个脚本文件(它应该是与使用src加载RequireJS是相同的脚本)。data-main需要给所有的脚本文件设置一个根路径。根据这个根路径,RequireJS将会去加载所有相关的模块。下面的脚本是一个使用data-main例子:

<script src="scripts/require.js" data-main="scripts/app.js"></script>

另外一种方式定义根路劲是使用配置函数,后面我们将会看到。requireJs假设所有的依赖都是脚本,那么当你声明一个脚本依赖的时候你不需要使用.js后缀。

NCThinker
NCThinker
翻译于 2013/08/15 10:01
2

配置函数

如果你想改变RequireJS的默认配置来使用自己的配置,你可以使用require.configh函数。config函数需要传入一个可选参数对象,这个可选参数对象包括了许多的配置参数选项。下面是一些你可以使用的配置:

  • baseUrl——用于加载模块的根路径。
  • paths——用于映射不存在根路径下面的模块路径。
  • shims——配置在脚本/模块外面并没有使用RequireJS的函数依赖并且初始化函数。假设underscore并没有使用  RequireJS定义,但是你还是想通过RequireJS来使用它,那么你就需要在配置中把它定义为一个shim。
  • deps——加载依赖关系数组

下面是使用配置的一个例子:

require.config({
    //By default load any module IDs from scripts/app
    baseUrl: 'scripts/app',
    //except, if the module ID starts with "lib"
     paths: {
        lib: '../lib'
    }, 
    // load backbone as a shim
    shim: {
        'backbone': {
            //The underscore script dependency should be loaded before loading backbone.js
            deps: ['underscore'],
            // use the global 'Backbone' as the module name.
            exports: 'Backbone'
        }
    }
});

在这个例子中把根路径设置为了scripts/app,由lib开始的每个模块都被配置在scripts/lib文件夹下面,backbone 加载的是一个shim依赖。

NCThinker
NCThinker
翻译于 2013/08/15 11:34
5

用RequireJS定义模块

模块是进行了内部实现封装、暴露接口和合理限制范围的对象。ReuqireJS提供了define函数用于定义模块。按章惯例每个Javascript文件只应该定义一个模块。define函数接受一个依赖数组和一个包含模块定义的函数。通常模块定义函数会把前面的数组中的依赖模块按顺序做为参数接收。例如,下面是一个简单的模块定义:

define(["logger"], function(logger) {        
        return {
             firstName: “John",
             lastName: “Black“,
             sayHello: function () {
                logger.log(‘hello’);
             }
        }
    }
);

我们看,一个包含了logger的模块依赖数组被传给了define函数,该模块后面会被调用。同样我们看所定义的模块中有一个名为logger的参数,它会被设置为logger模块。每一个模块都应该返回它的API.这个示例中我们有两个属性(firstName和lastName)和一个函数(sayHello)。然后,只要你后面定义的模块通过ID来引用这个模块,你就可以使用其暴露的API。

姜鹏飞
姜鹏飞
翻译于 2013/08/19 09:39
6

使用require函数

在RequireJS中另外一个非常有用的函数是require函数。require函数用于加载模块依赖但并不会创建一个模块。例如:下面就是使用require定义了能够使用jQuery的一个函数。

require(['jquery'], function ($) {
    //jQuery was loaded and can be used now
});

小结

在这篇文章中我介绍了RequireJS库,它是我创建每个Javascript项目都会用到的库函数之一。它不仅仅用于加载模块依赖和相关的命令,RequireJS帮助我们写出模块化的JavaScript代码,这非常有利于代码的可扩展性和重用性。

NCThinker
NCThinker
翻译于 2013/08/15 13:30
7
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(37)

kkkppp7979
kkkppp7979

引用来自“stackvirgi”的评论

data-main属性这段里最后一句: 另外一种方式定义根路'劲'是使用配置函数, 错别字...
:sweat:
请叫我小黄毛
两位兄弟讨论的很是激烈啊!不过,在下看来,关于require.js ,尔等认同也好,排斥也罢。他无疑是模块化最好的实现者之一。当下,前端模块化的呼声如此之高,乃至w3c新出台的ES6中也有相关内容,可见前端模块化已是大势所趋。
zhaoyou
zhaoyou

引用来自“jQer”的评论

引用来自“李惟”的评论

引用来自“jQer”的评论

引用来自“我是一名新人”的评论

引用来自“jQer”的评论

引用来自“我是一名新人”的评论

引用来自“jQer”的评论

引用来自“李惟”的评论

引用来自“jQer”的评论

引用来自“張凡”的评论

有沒有應用示例啊,看不出它的優勢哦

服务器用比较合适, 前端用会增加请求次数降低性能

你JS跟谁学的?不是这样的哦,传统的<script>存在几个问题:1.严格的读取顺序,多个文件互相依赖,依赖性最小的文件必须放在最前面,否则代码会报错;2.性能问题,浏览器采用"同步模式"加载<script>标签,也就是说,页面会"堵塞"。
##为了解决这些问题,可以使用DOM方法,动态加载Javascript文件。##,注意哦,动态加载JS,并不会造成性能问题,而是更好的解决JS性能问题

小孩子, 没有实战经验就别在这bb。 你去打听下谁家的商业站在浏览器端用require js的

多了去了,至少我知道,bat就有很多团队钻研这种,商业化场景也很多,举1,2个吧,百度统计,支付宝(支付宝用的是seajs,思想和这个差不多),commonjs,requirejs,seajs都是趋势啊

对于前端需要的是命名空间, 而不是文件路径。
require js 的目标就是一个文件一个类(对象), 调用某个对象时,直接通过对方的路径进行引用。
而对于前端, js文件最快速或者隐藏式的下载缓存到用户浏览器中, 以后不再要求用户对服务器请求js。 所有的js在合理的命名空间下管理。 一个懂请求的人怎么会用require js。

你不知道发布的时候有工具可以把所有的js打包到1个js文件吗?

如果在一个文件里, 你打算用require 多次一举的定义命名空间吗. 直接写个namespace() 函数就足够了

1.加载是加载,命名空间是命名空间,我不能说我有命名空间了,就不需要更好的加载方法了,这是两回事,这也是你的误区;2.require只是帮你更好的加载,但只是帮你更好的加载,而不是取代加载哦,他不会影响你的请求和再次请求

为什么 node.js采用了require js, juqery yui却不采用?

node.js 没有采用 require js. (require.js 是实现AMD 规范的一种)。Node.js 是实现的 Common Module define CMD )。当然 npm 里面是有requrejs 模块。
Ambitor
Ambitor
好激烈啊,看的好精彩啊。。哈哈 看了这么多 还是这位兄弟说的最恰当啊。。@simply哈哈
北京冰帆科技
北京冰帆科技

引用来自“jQer”的评论

引用来自“我是一名新人”的评论

引用来自“jQer”的评论

引用来自“我是一名新人”的评论

引用来自“jQer”的评论

引用来自“李惟”的评论

引用来自“jQer”的评论

引用来自“張凡”的评论

有沒有應用示例啊,看不出它的優勢哦

服务器用比较合适, 前端用会增加请求次数降低性能

你JS跟谁学的?不是这样的哦,传统的<script>存在几个问题:1.严格的读取顺序,多个文件互相依赖,依赖性最小的文件必须放在最前面,否则代码会报错;2.性能问题,浏览器采用"同步模式"加载<script>标签,也就是说,页面会"堵塞"。
##为了解决这些问题,可以使用DOM方法,动态加载Javascript文件。##,注意哦,动态加载JS,并不会造成性能问题,而是更好的解决JS性能问题

小孩子, 没有实战经验就别在这bb。 你去打听下谁家的商业站在浏览器端用require js的

多了去了,至少我知道,bat就有很多团队钻研这种,商业化场景也很多,举1,2个吧,百度统计,支付宝(支付宝用的是seajs,思想和这个差不多),commonjs,requirejs,seajs都是趋势啊

对于前端需要的是命名空间, 而不是文件路径。
require js 的目标就是一个文件一个类(对象), 调用某个对象时,直接通过对方的路径进行引用。
而对于前端, js文件最快速或者隐藏式的下载缓存到用户浏览器中, 以后不再要求用户对服务器请求js。 所有的js在合理的命名空间下管理。 一个懂请求的人怎么会用require js。

你不知道发布的时候有工具可以把所有的js打包到1个js文件吗?

如果在一个文件里, 你打算用require 多次一举的定义命名空间吗. 直接写个namespace() 函数就足够了

现在require js打包方案相当成熟,你能不能看一看别人的原理再来喷?现在稍微大点的公司都有用到require js,这个已经变成js的一个事实标准了,你就不要闭门造车了啊,多出去看看,好不?对了,你应该是小公司的吧?或者学生?
令狐乐儿
令狐乐儿
这个东西不是会增加页面的js的请求次数吗,这样做有必要?
simply
simply

引用来自“jQer”的评论

引用来自“李惟”的评论

引用来自“jQer”的评论

引用来自“我是一名新人”的评论

引用来自“jQer”的评论

引用来自“我是一名新人”的评论

引用来自“jQer”的评论

引用来自“李惟”的评论

引用来自“jQer”的评论

引用来自“張凡”的评论

有沒有應用示例啊,看不出它的優勢哦

服务器用比较合适, 前端用会增加请求次数降低性能

你JS跟谁学的?不是这样的哦,传统的<script>存在几个问题:1.严格的读取顺序,多个文件互相依赖,依赖性最小的文件必须放在最前面,否则代码会报错;2.性能问题,浏览器采用"同步模式"加载<script>标签,也就是说,页面会"堵塞"。
##为了解决这些问题,可以使用DOM方法,动态加载Javascript文件。##,注意哦,动态加载JS,并不会造成性能问题,而是更好的解决JS性能问题

小孩子, 没有实战经验就别在这bb。 你去打听下谁家的商业站在浏览器端用require js的

多了去了,至少我知道,bat就有很多团队钻研这种,商业化场景也很多,举1,2个吧,百度统计,支付宝(支付宝用的是seajs,思想和这个差不多),commonjs,requirejs,seajs都是趋势啊

对于前端需要的是命名空间, 而不是文件路径。
require js 的目标就是一个文件一个类(对象), 调用某个对象时,直接通过对方的路径进行引用。
而对于前端, js文件最快速或者隐藏式的下载缓存到用户浏览器中, 以后不再要求用户对服务器请求js。 所有的js在合理的命名空间下管理。 一个懂请求的人怎么会用require js。

你不知道发布的时候有工具可以把所有的js打包到1个js文件吗?

如果在一个文件里, 你打算用require 多次一举的定义命名空间吗. 直接写个namespace() 函数就足够了

1.加载是加载,命名空间是命名空间,我不能说我有命名空间了,就不需要更好的加载方法了,这是两回事,这也是你的误区;2.require只是帮你更好的加载,但只是帮你更好的加载,而不是取代加载哦,他不会影响你的请求和再次请求

为什么 node.js采用了require js, juqery yui却不采用?

这三个库你都没有说对厄..

首先, 没有 node.js 采用 require.js之说. node.js 是 commonJS 的一个实现.

其次, jQuery 在 1.7 版本加入 AMD 支持

何为 AMD? 度娘下吧. require.js 是AMD 的一个实现

最后, 关于 yui,
Y.add 也是一种异步模块加载.

你可以不用 require.js, 但是异步模块机制是发展所趋.

你所认知的 require.js 缺点 , AMD 社区早认识到, 并有相应的解决方案
niubo_
niubo_
前面的讨论还挺激烈的。不过话说RequireJS也好,AMD规范也好,确实存在很大争议,接触SeaJS的时候多少了解过一点。只能说每种技术都有特定的理念和设计哲学,很多都是针对某些特定范围的问题而出现的。从这点来看RequireJS肯定不是可以敲尽世间所有钉子的大锤。
技术人员在不同公司解决着不同的问题,使用着不同的技术,用久了肯定对自己熟悉的领域有着各种各样的心得和见解。你不能拿着自己熟悉的技术或者解决问题的思路非要跟别人一较高下对吧。解决问题的途径有很多种,每种都有自己的优缺点,每个人都可能出于不同的关注点来权衡。即使你用的是最优的解决方法,也并不是说用其他方法的人都是死路一条。
大家兴致勃勃讨论感兴趣的技术时突然插一脚上来劈头就是一句什“么狗屁玩意”——我只能说这种人只是不解风情而已,跟技术无关。
好了,看了前面这么多评论不吐不快……
niubo_
niubo_

引用来自“-萧-”的评论

这种写法让我想起来DOJO

因为新版的DOJO和RequireJS一样也开始遵守AMD规范了呗。
jQer
jQer

引用来自“李惟”的评论

引用来自“jQer”的评论

引用来自“李惟”的评论

引用来自“jQer”的评论

引用来自“我是一名新人”的评论

引用来自“jQer”的评论

引用来自“我是一名新人”的评论

引用来自“jQer”的评论

引用来自“李惟”的评论

引用来自“jQer”的评论

引用来自“張凡”的评论

有沒有應用示例啊,看不出它的優勢哦

服务器用比较合适, 前端用会增加请求次数降低性能

你JS跟谁学的?不是这样的哦,传统的<script>存在几个问题:1.严格的读取顺序,多个文件互相依赖,依赖性最小的文件必须放在最前面,否则代码会报错;2.性能问题,浏览器采用"同步模式"加载<script>标签,也就是说,页面会"堵塞"。
##为了解决这些问题,可以使用DOM方法,动态加载Javascript文件。##,注意哦,动态加载JS,并不会造成性能问题,而是更好的解决JS性能问题

小孩子, 没有实战经验就别在这bb。 你去打听下谁家的商业站在浏览器端用require js的

多了去了,至少我知道,bat就有很多团队钻研这种,商业化场景也很多,举1,2个吧,百度统计,支付宝(支付宝用的是seajs,思想和这个差不多),commonjs,requirejs,seajs都是趋势啊

对于前端需要的是命名空间, 而不是文件路径。
require js 的目标就是一个文件一个类(对象), 调用某个对象时,直接通过对方的路径进行引用。
而对于前端, js文件最快速或者隐藏式的下载缓存到用户浏览器中, 以后不再要求用户对服务器请求js。 所有的js在合理的命名空间下管理。 一个懂请求的人怎么会用require js。

你不知道发布的时候有工具可以把所有的js打包到1个js文件吗?

如果在一个文件里, 你打算用require 多次一举的定义命名空间吗. 直接写个namespace() 函数就足够了

1.加载是加载,命名空间是命名空间,我不能说我有命名空间了,就不需要更好的加载方法了,这是两回事,这也是你的误区;2.require只是帮你更好的加载,但只是帮你更好的加载,而不是取代加载哦,他不会影响你的请求和再次请求

对于你的技术, 我只能说你写的代码都是烂到家的文件依赖代码。
一个良好的js文件夹中的代码, 只有一个总框架文件和其他组件代码文件,依赖于这唯一一个文件。
还加载顺序, 先好好组织你的代码编写能力吧

诺,这不就是你的误区么,我想无论我、还是你,还是大家凡是尽力过公司项目开发,都应该切实感受到过:无论多大的项目,无论多大的公司,凡是多人项目开发的,必然会有多个JS文件,或者多请求,虽然这不是硬性规定,但却是避免不了,注意哦,我是在说实际,不是在说概念哦,大家想想是不是如此呢。更重要的是,我不能因为一些优点而摒弃其他的特点,举例子吧,比如说我有了命名空间,就放弃了请求,我不能因为目的是打包JS,而说明其他代码就不够好,我不能因为有了YUI,就说明node.js不对。就好比,不能因为面包不错,我们就放弃吃饭,你说是不是呢?

说什么呢, 多人合作啊, 共建一个文件, 好好跟你的同事协商好接口, 我觉得再跟你说下去就是废话了, 完全说不通了
返回顶部
顶部