nodejs模块
一、nodejs模块分类
1.核心模块 Core Module、内置模块、原生模块
- fs模块
- path模块
- I/O模块
- http模块
- ...
所有内置模块在安装nodejs的时候就已经编译成 二进制文件了,可以直接加载运行(速度较快),部分内置模块,在node.exe这个进程启动的时候就已经默认加载了,所以可以直接使用。
2.文件模块
按文件后缀来分
如果加载时,没有指定后缀名,那么就按照如下顺序一次家在相应模块
- .js
- .json
- .node(C/C++ 编写的模块)
3.自定义模块(第三方模块)
- .mime
- .cherrio
- .moment
- .mongo
- ...
二、require加载模块顺序
-
情形一:
require()的参数是一个路径- 路径带后缀
nodejs加载时会将路径还原为完整路径,根据这个完整路径从磁盘中找该文件。require(./index.js) - 路径不带后缀
先找require(./index)index.js文件 ---> 再找index.json文件 ---> 接着找index.node文件;找不到,当成index文件夹加载继续找,找到了,在index文件夹下面找package.json--->main(入口文件,查找app.js ---> index.js/ index.json/index.node);否则加载失败。
如下package.json:{ "name": "hackernews", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "mime": "^2.4.4", "underscore": "^1.9.1" } }
所以,我们在实际项目中要写上文件后缀。
- 路径带后缀
-
情形二:
require()的参数不是一个路径,直接是一个模块名称require('http')- 先在核心模块(core module)中查找是否有该模块,如果有直接加载核心模块。
- 若核心模块中没有找到,那么会被认为是一个第三方模块(自定义模块),接着先在当前文件所在的目录去找
node_modules文件夹,再node_modules中找对应的模块,否则在当前目录的父目录继续查找,直到磁盘根目录(上穷碧落)。
console.log(modules.paths); // 查看模块加载的路径顺序结果:
```[ 'D:\\studyFiles\\learning-note\\learn-node\\node_modules', 'D:\\studyFiles\\learning-note\\learn-node\\node_modules', 'D:\\studyFiles\\learning-note\\node_modules', 'D:\\studyFiles\\node_modules', 'D:\\node_modules' ] ```
三、require(同步方式,在module.js里面定义的)加载模块注意点
- 所有模块第一次加载完毕后都会有缓存,二次加载直接读取缓存,避免了二次开销;因为有缓存,所以模块中的代码只会在第一次加载的时候执行一次。
加载后会执行一次被加载的模块里面所有的代码,若多次加载只会在第一次加载的时候执行。 - 每次加载模块的时候都优先从缓存中加载,缓存中没有的情况下才会按照 nodejs 加载模块的规则区查找。
- 核心模块在 nodejs 源码变异的时候,都已经编译为二进制执行文件,所以加载速度较快(核心模块加载的优先级仅次于 缓存加载)
- 核心模块都保存在
lib目录下。 - 试图加载一个和 核心模块 同名的 自定义模块(第三方模块)是不会成功的,解决方式:
- 自定义模块要避免核心模块同名
- 自定义模块使用路径的方式加载
- 核心模块 只能通过 模块名称 来加载。
require('./http') // 这样只能当成第三方模块来加载 -
require()加载模块使用./相对路径时,相对路径是相对于当前模块,不受执行的 node 命令的路径影响。 - 建议加载文件模块的时候始终添加文件后缀名,不要省略。
- 一个模块加载另一个模块用
require(),一个模块暴露属性给另一个模块用module.exports。
补充:CommonJS规范
- CommonJS规范
- 模块的定义
- CommonJS是为 javascript 语言指定的一种 模块规范、编程API规范,nodejs 遵循了该规范。
关于 nodejs中 module 详细介绍
附: nodejs 官网 关于require()加载模块主要做了什么的详情解释
```
require(X) from module at path Y
1. If X is a core module,
a. return the core module
b. STOP
2. If X begins with '/'
a. set Y to be the filesystem root
3. If X begins with './' or '/' or '../'
a. LOAD_AS_FILE(Y + X)
b. LOAD_AS_DIRECTORY(Y + X)
4. LOAD_NODE_MODULES(X, dirname(Y))
5. THROW "not found"
LOAD_AS_FILE(X)
1. If X is a file, load X as JavaScript text. STOP
2. If X.js is a file, load X.js as JavaScript text. STOP
3. If X.json is a file, parse X.json to a JavaScript Object. STOP
4. If X.node is a file, load X.node as binary addon. STOP
LOAD_INDEX(X)
1. If X/index.js is a file, load X/index.js as JavaScript text. STOP
2. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP
3. If X/index.node is a file, load X/index.node as binary addon. STOP
LOAD_AS_DIRECTORY(X)
1. If X/package.json is a file,
a. Parse X/package.json, and look for "main" field.
b. If "main" is a falsy value, GOTO 2.
c. let M = X + (json main field)
d. LOAD_AS_FILE(M)
e. LOAD_INDEX(M)
f. LOAD_INDEX(X) DEPRECATED
g. THROW "not found"
2. LOAD_INDEX(X)
LOAD_NODE_MODULES(X, START)
1. let DIRS = NODE_MODULES_PATHS(START)
2. for each DIR in DIRS:
a. LOAD_AS_FILE(DIR/X)
b. LOAD_AS_DIRECTORY(DIR/X)
NODE_MODULES_PATHS(START)
1. let PARTS = path split(START)
2. let I = count of PARTS - 1
3. let DIRS = [GLOBAL_FOLDERS]
4. while I >= 0,
a. if PARTS[I] = "node_modules" CONTINUE
b. DIR = path join(PARTS[0 .. I] + "node_modules")
c. DIRS = DIRS + DIR
d. let I = I - 1
5. return DIRS
```











网友评论