[TOC]
# 简介
[RequireJS](http://requirejs.org/docs/api.html)是一个工具库,主要用于客户端的模块管理。它可以让客户端的代码分成一个个模块,实现异步或动态加载,从而提高代码的性能和可维护性。它的模块管理遵守AMD规范(Asynchronous Module Definition)。
RequireJS的基本思想是:
* 通过define方法,将代码定义为模块;
* 通过require方法,实现代码的模块加载。
首先,将require.js嵌入网页,然后就能在网页中进行模块化编程了。
## 按需加载效果 -- 示例
如果点击了页面,则会有一个脚本`selector.js`进行下载。
**在代码中 `require` 一个文件多次,是否会导致浏览器反复加载?
不会,这是 RequrieJS 的优点,即使你反复 `require` 它,它只加载一次。**
```
require(['jquery', 'event'], function($, E) {
$(document).click(function(){
require(['selector'], function (ko) {
alert("selector is downloading!!!");
});
alert("selector is Downloaded!!!");
});
});
```
## 加载 RequireJS 的方式
方式一:
```html
<script src="./js/require.js"></script>
<script>
require(["./js/a.js", "./js/b.js"], function() {
myFunctionA();
myFunctionB();
});
</script>
```
require 方法里的这个字符串数组参数可以允许不同的值,当字符串是以”.js”结尾,或者以”/”开头,或者就是一个 URL 时,RequireJS 会认为用户是在直接加载一个 JavaScript 文件,否则,**当字符串是类似”my/module”的时候,它会认为这是一个模块**,并且会以用户配置的 baseUrl 和 paths 来加载相应的模块所在的 JavaScript 文件。
方式二:
```html
<script data-main="js/main" src="scripts/require.js"></script>
```
则 `data-main` 指定了一个在当前 `index.html` 目录并行的文件夹下的 `/js/main.js` 作为程序入口,而 `/js` 目录也将作为`baseUrl`在其他模块定义时候使用。
用户自定义的代码就放在这个`main.js`文件中。
## baseUrl
```html
<script type="text/javascript" src="./js/require.js"></script>
<script type="text/javascript">
require.config({
baseUrl: "./js",
paths: {
"some": "some/v1"
},
waitSeconds: 10
});
require( ["some/module", "my/module", "./js/a.js"],
function(someModule, myModule) {}
);
</script>
```
`baseUrl`指明的是所有模块的 base URL,比如`my/module`所加载的 script实际上就是 `/js/my/module.js`。注意,以 `.js` 结尾的文件加载时不会使用该 `baseUrl`,它们仍然会使用当前 `index.html`所在的相对路径来加载,所以仍然要加上`./js/`。如果 `baseUrl`没有指定,那么就会使用 `data-main`中指定的路径。
`paths` 中定义的路径是用于替换模块中的路径,如上例中的 `some/module` 具体的 JavaScript 文件路径是 `/js/some/v1/module.js` 。
`waitSeconds`是指定最多花多长等待时间来加载一个 JavaScript 文件,用户不指定的情况下默认为 7 秒。
# `require()`
示例:
```js
require(['jquery', 'script/hello'],function ($, hello) {
$("#btn").click(function(){
hello.showMessage("hangge.com");
});
});
```
# `define()`
## [定义一个带有名称的模块](http://requirejs.org/docs/api.html#modulename)
你可能会遇到一些第一个参数是有名字的`define()`函数,例如:
```js
//Explicitly defines the "foo/title" module:
define("foo/title",
["my/cart", "my/inventory"],
function(cart, inventory) {
//Define foo/title object in here.
}
);
```
这些通常是由优化工具(`r.js`)生成的。您可以自己显式地命名模块,但是**它会使模块的可移植性更低——如果将文件移动到另一个目录,则需要更改其名称**。通常最好避免在模块名称中进行编码,并让优化工具去灌入模块名。优**化工具需要添加名称,以便将多个模块打包在一个文件中,让浏览器更快地加载**。
# 模块的定义
* 模块不同于传统的脚本文件,它良好地定义了一个作用域来避免全局名称空间污染。
* 它可以显式地列出其依赖关系,并以函数(定义此模块的那个函数)参数的形式将这些依赖进行注入,而无需引用全局变量。同时因为无需创建全局变量,甚至可以做到在同一个页面上同时加载同一模块的不同版本。
* RequireJS 的模块语法允许它尽快地加载多个模块,虽然加载的顺序不定,但依赖的顺序最终是正确的。
* 一个js文件应该只定义 1 个模块。**多个模块可以使用内置优化工具将其组织打包**。
## 模块间的依赖关系
* 模块间的依赖关系如何定义。还是有一些使用技巧需要提示一下:
* 尽量不要提供模块的 ID,如 AMD 规范所述,这个 ID 是可选项,如果提供了,在 RequireJS 的实现中会影响模块的可迁移性,文件位置变化会导致需要手动修改该 ID。
* 每个 JavaScript 文件只定义一个模块,模块名称和文件路径的查找算法决定了这种方式是最优的,多个的模块和文件会被优化器进行优化。
* 避免模块的循环依赖,如果实在避免不了,可以模块中加上对`require`模块的依赖,在代码中直接用 `require(”dependencyModuleName”)`。
# 错误处理
1. 全局的错误捕获:`require.onError`
为了捕获在局域的 `errback` 中未捕获的异常,可以重载 `require.onError()` 来实现全局的异常捕获。
```js
require.onError = function (err) {
console.log(err.requireType);
if (err.requireType === 'timeout') {
console.log('modules: ' + err.requireModules);
}
throw err;
};
```
# 多页面项目使用requireJS
[requirejs的入口文件是有且只有一个吗?](http://www.imooc.com/qadetail/52210)
我也有这个疑问,查了github上的资料,对于多个页面的话,`requirejs` 的 `config` 是可以做到多个页面共享的,而每个页面的有自己单独的入口js ,每个入口js首先会加载配置路径的文件,然后再写自己页面的逻辑。
官方示例:https://github.com/requirejs/example-multipage
# 参考
[优化网站设计(十七):延迟或按需加载内容](http://www.cnblogs.com/chenxizhang/archive/2013/05/16/3081941.html)
[RequireJS - 入门指南、进阶使用详解](http://www.hangge.com/blog/cache/detail_1702.html)
[基于gulp requirejs rjs的前端自动化构建系列文章(二)](http://hcysun.me/2015/11/14/基于gulp-requirejs-rjs的前端自动化构建系列文章-二/)
https://github.com/ruanyf/jstutorial/blob/gh-pages/tool/requirejs.md
- 讲解 Markdown
- 示例
- SVN
- Git笔记
- github 相关
- DESIGNER'S GUIDE TO DPI
- JS 模块化
- CommonJS、AMD、CMD、UMD、ES6
- AMD
- RequrieJS
- r.js
- 模块化打包
- 学习Chrome DevTools
- chrome://inspect
- Chrome DevTools 之 Elements
- Chrome DevTools 之 Console
- Chrome DevTools 之 Sources
- Chrome DevTools 之 Network
- Chrome DevTools 之 Memory
- Chrome DevTools 之 Performance
- Chrome DevTools 之 Resources
- Chrome DevTools 之 Security
- Chrome DevTools 之 Audits
- 技巧
- Node.js
- 基础知识
- package.json 详解
- corepack
- npm
- yarn
- pnpm
- yalc
- 库处理
- Babel
- 相关库
- 转译基础
- 插件
- AST
- Rollup
- 基础
- 插件
- Webpack
- 详解配置
- 实现 loader
- webpack 进阶
- plugin 用法
- 辅助工具
- 解答疑惑
- 开发工具集合
- 花样百出的打包工具
- 纷杂的构建系统
- monorepo
- 前端工作流
- 爬虫
- 测试篇
- 综合
- Jest
- playwright
- Puppeteer
- cypress
- webdriverIO
- TestCafe
- 其他
- 工程开发
- gulp篇
- Building With Gulp
- Sass篇
- PostCSS篇
- combo服务
- 编码规范检查
- 前端优化
- 优化策略
- 高性能HTML5
- 浏览器端性能
- 前后端分离篇
- 分离部署
- API 文档框架
- 项目开发环境
- 基于 JWT 的 Token 认证
- 扯皮时间
- 持续集成及后续服务
- 静态服务器搭建
- mock与调试
- browserslist
- Project Starter
- Docker
- 文档网站生成
- ddd