require 用來加載一個文件的代碼
簡單概括以下幾點:
- require 可加載 .js、.json 和 .node 后綴的文件
- require 的過程是同步的,所以這樣是錯誤的:
setTimeout(() => {
module.exports = { a: 'hello' };
}, 0);
require這個文件得到的是一個空對象{}
- require的目錄機制:
- 第一種方式是在根目錄下創建一個 package.json 文件,并指定一個 main 模塊。 例子,package.json 文件類似:
{ "name" : "app",
"main" : "./lib/app.js" }
如果這是在 ./app 目錄中,則 require('./app') 會試圖加載 ./app/lib/app.js。
這就是 Node.js 處理 package.json 文件的方式。
注意:如果 package.json 中 "main" 入口指定的文件不存在,則無法解析,Node.js 會將模塊視為不存在,并拋出默認錯誤:
Error: Cannot find module 'some-library'
-
如果目錄里沒有 package.json 文件,則 Node.js 就會試圖加載目錄下的 index.js 或 index.node 文件。如果上面的例子中沒有 package.json 文件,則 require('./app') 會試圖加載:
./app/index.js
./app/index.node
-
require的文件模塊
- 如果按確切的文件名沒有找到模塊,則 Node.js 會嘗試帶上 .js、.json 或 .node 拓展名再加載。
- .js文件會被解析為 JavaScript 文本文件,.json 文件會被解析為 JSON 文本文件。 .node文件會被解析為通過 dlopen加載的編譯后的插件模塊。
- 以 '/'為前綴的模塊是文件的絕對路徑。 例如require('/home/app/app.js')會加載 /home/app/app.js
文件。 - 以 './'為前綴的模塊是相對于調用 require()的文件的。 也就是說,circle.js必須和 app.js在同一目錄下以便于 require('./circle') 找到它。
- 當沒有以 '/'、'./'或 '../' 開頭來表示文件時,這個模塊必須是一個核心模塊或加載自 node_modules 目錄。如果給定的路徑不存在,則 require()會拋出一個 code屬性為 'MODULE_NOT_FOUND'
的 Error。
-
require的緩存機制
- 模塊在第一次加載后會被緩存。 這也意味著(類似其他緩存機制)如果每次調用 require('app') 都解析到同一文件,則返回相同的對象。
- 多次調用 require('app') 不會導致模塊的代碼被執行多次。 這是一個重要的特性。如果想要多次執行一個模塊,可以導出一個函數,然后調用該函數。
注意事項: - 模塊是基于其解析的文件名進行緩存的。 由于調用模塊的位置的不同,模塊可能被解析成不同的文件名。
- 此外,在不區分大小寫的文件系統或操作系統中,被解析成不同的文件名可以指向同一文件,但緩存仍然會將它們視為不同的模塊,并多次重新加載。 例如,require('./app') 和 require('./APP') 返回兩個不同的對象,而不會管 ./app 和 ./APP 是否是相同的文件。