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 是否是相同的文件。