RequireJS异步模块加载

从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发。Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎。chrome浏览器就基于V8,同时打开20-30个网页都很流畅。Nodejs标准的web开发框架Express,可以帮助我们迅速建立web站点,比起PHP的开发效率更高,而且学习曲线更低。非常适合小型网站,个性化网站,我们自己的Geek网站!!

关于作者

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/nodejs-requirejs/

requirejs

前言

随着项目越来越大,依赖越来越多,代码的耦合度也越来越高。我们需要从架构的层面设计和优化代码的组织结构。RequireJS遵循AMD(异步模块定义)规范,从架构层抽象出“模块化”开发方案,并以标准化了模块化开发,同时和其他的开发框架保持兼容。

按照RequireJS的规范,我们能够更容易地实现更复杂,更强大的JS的富客户端程序。

目录

  1. RequireJS介绍
  2. RequireJS安装
  3. RequireJS基本使用
  4. nodejs构建简易的web服务器
  5. RequireJS模块化
  6. 多路径配置: baseUrl,paths
  7. 编译Requirejs模块

1. RequireJS介绍

RequireJS是一个Javascript的模块加载器,倡导的是一种模块化开发理念,核心价值是让 JavaScript 的模块化开发变得更简单自然。RequireJS 遵循的是 AMD(异步模块定义)规范,帮助用户异步按需的加载 JavaScript 代码,并解决 JavaScript 模块间的依赖关系,提升了前端代码的整体质量和性能。

2. RequireJS安装

我的系统环境

  • win7 64bit
  • Nodejs:v0.10.5
  • Npm:1.2.19

通过nodejs安装RequireJS


~ D:\workspace\javascript>mkdir nodejs-require && cd nodejs-require
~ D:\workspace\javascript\nodejs-require>npm install requirejs
npm http GET https://registry.npmjs.org/requirejs
npm http 200 https://registry.npmjs.org/requirejs
requirejs@2.1.8 node_modules\requirejs

全局安装requirejs:使用r.js工具。


~ D:\workspace\javascript\nodejs-require>npm install requirejs -g
npm http GET https://registry.npmjs.org/requirejs
npm http 304 https://registry.npmjs.org/requirejs
D:\toolkit\nodejs\r.js -> D:\toolkit\nodejs\node_modules\requirejs\bin\r.js
npm ERR! peerinvalid The package generator-karma does not satisfy its siblings' peerDependencies requirements!
npm ERR! peerinvalid Peer generator-angular@0.4.0 wants generator-karma@~0.5.0

npm ERR! System Windows_NT 6.1.7601
npm ERR! command "D:\\toolkit\\nodejs\\\\node.exe" "D:\\toolkit\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install" "
requirejs" "-g"
npm ERR! cwd D:\workspace\javascript\nodejs-require
npm ERR! node -v v0.10.5
npm ERR! npm -v 1.2.19
npm ERR! code EPEERINVALID
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR!     D:\workspace\javascript\nodejs-require\npm-debug.log
npm ERR! not ok code 0

运行r.js命令失败


~ D:\workspace\javascript\nodejs-require>r.js

requirejs-rjs

我的win7环境中有错误,所以我只能在当前项目中运行r.js命令.(Linux下面可以全局安装。)


~ D:\workspace\javascript\nodejs-require>node node_modules\requirejs\bin\r.js -h
See https://github.com/jrburke/r.js for usage.

3. RequireJS基本使用

创建项目文件:


~ D:\workspace\javascript\nodejs-require>ls -l
-rwx------  1 4294967295 mkpasswd  65 Sep 19 13:32 a.js
-rwx------  1 4294967295 mkpasswd  59 Sep 18 20:33 b.js
-rwx------  1 4294967295 mkpasswd  82 Sep 18 20:33 c.js
-rwx------  1 4294967295 mkpasswd  69 Sep 18 20:33 d.js
-rwx------  1 4294967295 mkpasswd 206 Sep 19 13:32 index.html
-rwx------  1 4294967295 mkpasswd  48 Sep 19 13:31 main.js
drwx------+ 1 4294967295 mkpasswd   0 Sep 18 20:32 node_modules

对文件的定义:

  • index.html: 用于加载javascript文件,这里只加载RequireJS库
  • main.js: RequireJS的模块组,用来封装JS模块,通过js来加载其他的js文件
  • a.js: 一个JS的功能文件,不依赖其他库
  • b.js: 一个JS的功能文件,不依赖其他库
  • c.js: 一个JS的功能文件,依赖a.js和b.js
  • d.js: 一个JS的功能文件,依赖c.js

新增文件:index.html


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>RequireJS</title>
<script data-main="main" src="node_modules/requirejs/require.js"></script>
</head>
<h1>RequireJS Testing</h1>
<body>
</body>
</html>

新增文件:main.js


require(['a'],function(){
     a();
})

新增文件:a.js


function a(){
    console.log("aaaaaaaaaaaaaaaaaaaaaaaaaaa");
}

新增文件:b.js


function b(){
    console.log("bbbbbbbbbbbbbbbbbbbbb");
}

新增文件:c.js


function c(){
    a();
    b();
    console.log("cccccccccccccccccccccccc");
}

新增文件:d.js


function d(){
    c();
    console.log("ddddddddddddddddddddd");
}

打开浏览器:file:///D:/workspace/javascript/nodejs-require/index.html

requirejs-testing1

我们发现a.js被加载了,但我们并没有在index.html中定义script加载a.js。

  • 1. a.js的加载是RequireJS帮我们做的。
  • 2. 通过在HTML中定义data-main属性,注册一个模块main.js。
  • 3. 在main.js中,通过声明式定义,引入a.js文件
  • 4. 实现了对a.js加载的控制

通过require函数完全成了依赖管理的功能

require(dependencies, callback)
  • dependencies: 是我们要载入的js,使用相对路径。
  • callback: 是封装有程序逻辑。

所以,我们可以发现了RequireJS可以帮我们做,js依赖管理。我们可以再也不用在HTML中,以很土的加载顺序的方式管理JS文件了。这种优雅的注入可以帮我很好的管理全局变量。

4. nodejs构建简易的web服务器

在进行下一步之前,我们要用构建一个简易的web服务器,RequireJS的模块化加载需要web server的支持,通过本地文件的方式是不行的。

安装connect依赖


~ D:\workspace\javascript\nodejs-require>npm install connect
connect@2.9.0 node_modules\connect
├── uid2@0.0.2
├── methods@0.0.1
├── cookie-signature@1.0.1
├── pause@0.0.1
├── fresh@0.2.0
├── bytes@0.2.0
├── qs@0.6.5
├── buffer-crc32@0.2.1
├── cookie@0.1.0
├── debug@0.7.2
├── send@0.1.4 (range-parser@0.0.4, mime@1.2.11)
└── multiparty@2.1.8 (stream-counter@0.1.0, readable-stream@1.0.17)

新建文件:app.js


~ vi app.js

var connect = require('connect');
connect.createServer(
    connect.static(__dirname)
).listen(3000);

开发模式启动服务器:

supervisor app.js

打开浏览器:http://localhost:3000
requirejs-testing2

5. RequireJS模块化

虽然我们可以把所有的程序都写在main.js的callback中,但是程序会变得复杂,关系也不清楚。接下来,我们要做模块化的编程。RequireJS也实现了AMD定义的define的API。

define(id?, dependencies?, factory)
  • id:字符串,模块名称,可选。
  • dependencies: 是我们要载入的js,使用相对路径。
  • factory: 工厂方法,返回一个模块函数

新建ab.js,实现模块ab:


~ vi ab.js

define(function(){
    return {
        a: function(){
            a();
            console.log("ab.a()");
        },
        b:function(){
            b();
            console.log("ab.b()");
        }
    };
});

修改main.js


~ vi main.js

require(['a','b','ab'],function(a,b,ab){
    ab.b();
})

刷新页面:http://localhost:3000/

requirejs-testing3

调用流程:

  • 1. 通过main.js加载了a.js,b.js,ab.js文件
  • 2. ab.js构建一个ab的模块
  • 3. 在ab的模块中,调用b.js的b()函数

通过模块化的封装后,我们可以更优化我们的程序,程序结构更清晰!

6. 多路径配置: baseUrl,paths

如果我们需要加载多个js文件时,文件在不同的目录下面,我们可以通过baseUrl和paths来设置路径的默认位置和路径别名,方便我们定位文件。


#新建目录
~ mkdir folder
~ mkdir folder/f1
~ mkdir folder/f2

#把c.js移动到f1
~ mv c.js folder/f1

#把d.js移动到f2
~ mv d.js folder/f2

修改main.js


~ vi main.js
require.config({
    baseUrl:'./',
    paths:{
        f1:'folder/f1',
        f2:'folder/f2'
    }
});

require([
    'b',
    'a',
    'ab',
    'f1/c',
    'f2/d'
],function(a,b,ab,c){
    d();
})

刷新浏览器:

requirejs-testing4

我们看到c.js, d.js都被正确的加载了。

7. 编译Requirejs模块

最后要讲的是,通过r.js命令,对模块进行翻译优化。

在RequireJS安装部分,我们没有实现全局安装,因些只能在项目中通过相对路径使用r.js的命令。


~ D:\workspace\javascript\nodejs-require>node node_modules\requirejs\bin\r.js -o name=main out=main-build.js baseUrl=. pat
hs.f1="folder/f1" paths.f2="folder/f2"

Tracing dependencies for: main
Uglifying file: D:/workspace/javascript/nodejs-require/main-build.js

D:/workspace/javascript/nodejs-require/main-build.js
----------------
D:/workspace/javascript/nodejs-require/b.js
D:/workspace/javascript/nodejs-require/a.js
D:/workspace/javascript/nodejs-require/ab.js
D:/workspace/javascript/nodejs-require/folder/f1/c.js
D:/workspace/javascript/nodejs-require/folder/f2/d.js
D:/workspace/javascript/nodejs-require/main.js

我们会发现,新生成一个文件main-build.js


~ cat main-build.js

function b(){console.log("bbbbbbbbbbbbbbbbbbbbb")}function a(){console.log("aaaaaaaaaaaaaaaaaaaaaaaaaaa")}function c(){a(),b(),console.log("cccccccccccccccccccccccc")}function d(){c(),console.log("ddddddddddddddddddddd")}define("b",function(){}),define("a",function(){}),define("ab",[],function(){return{a:function(){a(),console.log("ab.a()")},b:function(){b(),console.log("ab.b()")}}}),define("f1/c",function(){}),define("f2/d",function(){}),require.config({baseUrl:"./",paths:{f1:"folder/f1",f2:"folder/f2"}}),require(["b","a","ab","f1/c","f2/d"],function(e,t,n,r){d()}),define("main",function(){});

新生成的main-build.js可以用来做为发布的功能模块。

本文简单的介绍了RequireJS的使用,如果我们的程序按照AMD的模块化思路去构建,我相信JS的代码,也是健壮的,可维护的,可传递的。

转载请注明出处:
http://blog.fens.me/nodejs-requirejs/

打赏作者

This entry was posted in Javascript语言实践, 架构设计

关于requireJS的同步加载异步加载 这篇随笔主要记录require('name')和require(['name1','name2'])在同步和异步加载使用的区别 1、require('name')同步加载模块的形式 define(function(require, exports, module) { var a = require('a'), b = requi... 阅读详情

相关推荐

详解JS的四种异步解决方案!(新增了相亲小栏目~)

大家好,我是若川。我持续组织了近一年的源码共读活动,感兴趣的可以点此扫码加我微信lxchuan12参与,每周大家一起学习200行左右的源码,共同进步。新增两位小姐姐和一位小哥哥:现有【L01】,【L02】,【L03】三个小姐姐,【N01】 一个小哥哥。具体在我的#公众号:若川视野 发消息回复 相应的关键词 获取微信号,或者查看文末。「异步编程」是前端工程师日常开发中经常会用到的技术,也是校...

u012384510的博客 1383

JavaScript异步编程模型

JavaScript异步编程模型

qqrrjj2011的博客 1811

异步加载requirejs,你值得拥有

1、综述: RequireJS的目标是代码的模块化,它使用了不同于传统<script>标签的脚本加载步骤。可以用它来加速代码加载、优化代码,但其主要目的还是为了代码的模块化。2、加载js文件 RequireJS以一个相对于baseUrl的地址来加载所有的代码。 <script>标签含有一个特殊的属性data-main,require.js使用它来...

weixin_33887443的博客 196

js异步模型

笔者以前面试的时候经常遇到写一堆setTimeout,setImmediate来问哪个先执行。本文主要就是来讲这个问题的,但是不是简单的讲讲哪个先,哪个后。笼统的知道setImmediate比setTimeout(fn, 0)先执行是不够的,因为有些情况下setTimeout(fn, 0)是会比setImmediate先执行的。要彻底搞明白这个问题,我们需要系统的学习JS的异步机制和底层原理。本文就会从异步基本概念出发,一直讲到Event Loop的底层原理,让你彻底搞懂setTimeout,setImme

萌古大汗的专栏 353

requirejs 加载html,异步加载requireJS模块内嵌HTML体?

我正在将RequireJS集成到CMS中,因此我将其放在我的页面模板的底部:{Placeholder1}{Placeholder2}然后在每个页面上,我想创建一个利用RequireJS的功能.所以我试着把它放在页面的底部:HomeSlider contentrequire(['jquery','utils','slider'], function ($, utils, slider) {slide...

weixin_39722196的博客 273

requirejs解决异步模块加载方案

他首先会遍历enableRegistry取出其中定义的模块,并且将没有加载成功的模块标识注入noLoads数组,如果过期了这里就会报错 如果上述没问题还会做循环依赖的判断,主要逻辑在breakCycle中,因为我们这里不存在循环依赖便跳出了,但还未结束 我们这里开始了递归检测依赖是否载入 if ((!expired || usingPathFallback) && sti...

weixin_30342827的博客 155

为什么说ajax,requirejs异步的?

requirejs(["a","b"],function(){ 代码段c }) ajax异步是等服务器发送数据来了就调用回调,但是数据处理是在服务器端完成的,这个时候客户端是异步的, 可是如果在浏览器端,,只有一个主进程,,,a代码执行,如果是需要5s,那必定要等5s然后c才运行,这个通过回调和直接按照顺序有什么不一样么? 已经头大了,期待好心人解答疑惑.... 因

u010523770的专栏 1192

RequireJS使用注意地方

使用RequireJS异步模块加载,有几点值得注意的地方: 1.模块定义两种写法 1.存在依赖的函数式定义 如果模块存在依赖:则第一个参数是依赖的名称数组;第二个参数是函数,在模块的所有依赖加载完...

weixin_39037804的博客 154

requirejs源码分析: requirejs 方法–1. 主入口

该方法是 主要的入口点 也是最常用的方法。 req = requirejs = function (deps, callback, errback, optional) { //Find the right context, use default var context, config, contextName = d...

194

AngularJS - 使用RequireJS还是Browserify?

http://www.html-js.com/article/2126 AngularJS - 使用RequireJS还是Browserify? AngularJS之所以吸引了很多开发者的关注,很大一部分原因是因为它为你如何架构你的应用提供了一种选择。通常来说,很多的选择并不是什么好事,因为觉得多数开发者并不希望你把一个“正确的”应用架构模式强加给他们。 就JavaSc...

dechen6073的博客 119

requireJS源码学习03】细究requireJS加载流程

requireJS源码学习03】细究requireJS加载流程 前言 这个星期折腾了一周,中间没有什么时间学习,周末又干了些其它事情,这个时候正好有时间,我们一起来继续学习requireJS吧 还是那句话,小钗觉得requireJS本身还是有点难度的,估计完全吸收这个月就过去了...

chym18845095620的博客 164

RequireJs 源码剖析脚本加载原理

引言   俗话说的好,不喜欢研究原理的程序员不是好的程序员,不喜欢读源码的程序员不是好的 jser。这两天看到了有关前端模块化的问题,才发现 JavaScript 社区为了前端工程化真是煞费苦心。今...

Wang1996332的博客 276

深入浅出 AMD 模块化使用

CommonJS 的缺点之一是它是同步的,AMD 旨在通过规范中定义的 API 异步加载模块及其依赖项来解决这个问题。AMD 全称为 Asynchronous Module Definition,即异步模块加载机制。它规定了如何定义模块,如何对外输出,如何引入依赖。AMD规范重要特性就是异步加载。所谓异步加载,就是指同时并发加载所依赖的模块,当所有依赖模块加载完成之后,再执行当前模块的回调函数。这种加载方式和浏览器环境的性能需求刚好吻合。// 模块内容});

前端梦工厂 888

Dojo 1.6 新特性: 异步模块加载机制AMD

本文翻译自: Asynchronous Modules Come to Dojo 1.6原作者:   Kris ZypDojo 1.6 中首次引入异步模块加载机制在最新的1.6 版本中,Dojo(Core) 和Dijit 已经通过重构引入了符合CommonsJS AMD API规范的异步模块加载机制(AMD) 模块的兼容性通过重构,现在Dojo的模块已经完全和下列框架兼容:RequireJSNodules , Node.js 的一个子项目用来处理模块加载Backdraft Framework , Do

Dojo中文博客 6351

REQUIRE.JS和SEA.JS模块加载JS

随着网站功能逐渐丰富,网页中的js也变得越来越复杂和臃肿,原有通过script标签来导入一个个的js文件这种方式已经不能满足现在互联网开发模式,我们需要团队协作、模块复用、单元测试等等一系列复杂的需求。 REQUIRE.JS和SEA.JS两者的相同之处RequireJS 和 SeaJS 都是模块加载器,倡导的是一种模块化开发理念,核心价值是让 JavaScript模块化开发变得更简单自然。不同之

alokka的博客 1192

JavaScript模块化开发——AMD规范

本文介绍一下AMD规范(注意,这里的AMD和做cpu的AMD可不是一回事)。 根据之前文章的知识,我们知道一个模块系统最起码要有下面这些功能: 可以创建封装的模块 可以定义对其他模块的依赖 可以导出功能,被其他模块使用 AMD是“Asynchronous Module Definition”的缩写,意思就是“异步模块定义”。从名称上就可以看出,它是通过异步方式加载模块

明天回火星 566
上一篇: R和JSON的傻瓜式编程
下一篇: 开发kettle插件 环境搭建
Fens
博客等级 码龄25年 126粉丝 277原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值