[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