共计 4409 个字符,预计需要花费 12 分钟才能阅读完成。
一、写在后面
为了对立 Javascript 在浏览器之外的实现,CommonJS 诞生了,CommonJS 试图定义一套一般应用程序应用的 API,从而填补 JavaScript 规范库过于简略的有余。CommonJS 标准包含了模块、包、零碎、控制台、文件系统、单元测试等局部。
Node.js 是目前 CommonJS 标准最热门的一个实现,随着 CommonJS 标准的更新,Node.js 也在一直跟进,但 Node.js 并不齐全遵循 CommonJS 标准。这是所有标准制定者都会遇到的难堪场面,因为标准的制订总是滞后于技术的倒退。
二、node 模块化
模块(Module)和包(Package)是 Node.js 最重要的支柱,开发一个具备肯定规模的程序不可能只用一个文件,通常须要把各个性能拆分、封装,而后组合起来,模块正是为了实现这种形式而诞生。
在浏览器 JavaScript 中,脚本模块的拆分和组合通常应用 HTML 的 script 标签来实现。Node.js 提供了 require 函数来调用其余模块,而且模块都是基于文件的,换句话说就是每个文件都是一个模块,机制非常简略。
模块类型
nodejs 的模块能够分为两类,一类是外围模块,另一类是文件模块。
外围模块 是 nodejs 官网提供的,node 过程启动时,局部外围模块就被间接加载进内存中,所以这部分外围模块咱们就能够间接通过 require 进行引入。比方 http 模块、url 模块、fs 模块等。
const http = require('http'); // 内置模块间接援用
const host = '127.0.0.1';
const port = 3000;
const server = http.createServer((req,res) => {
res.statusCode = 200;
res.end('test1');
})
server.listen(port, host, () => {console.log(` 服务器运行在 http://${host}:${port}/`)
})
文件模块 是在运行时动静加载,须要残缺的路径分析、文件定位、编译执行过程、速度相比外围模块略微慢一些,然而用的十分多。文件模块的加载形式有两种,一种是按门路加载,另一种是查找 node_modules
文件夹。
按门路加载模式
// custom_module 文件夹下的 tools 文件
function calculate(num) {return num*2}
function getUrl(domain) {return `${domain}/wanwan0306`
}
module.exports = {
calculate,
getUrl
}
// app.js
const http = require('http');
const {calculate, getUrl} = require('./custom_module/tools'); // 按门路引入
const host = '127.0.0.1';
const port = 3100;
const server = http.createServer((req,res) => {const num = calculate(20);
const url = getUrl('https');
res.statusCode = 200;
res.end(`${num}-${url}-test2`);
})
server.listen(port, host, () => {console.log(` 服务器运行在 http://${host}:${port}/`)
})
node_modules 文件夹加载模式
// node_modules 文件夹下的 tools 文件
function calculate(num) {return num*2}
function getUrl(domain) {return `${domain}/wanwan0306`
}
module.exports = {
calculate,
getUrl
}
// app.js
const http = require('http');
const {calculate, getUrl} = require('tools'); // node_modules
const host = '127.0.0.1';
const port = 3200;
const server = http.createServer((req,res) => {const num = calculate(20);
const url = getUrl('https');
res.statusCode = 200;
res.end(`${num}-${url}-test3`);
})
server.listen(port, host, () => {console.log(` 服务器运行在 http://${host}:${port}/`)
})
加载规定
1. 如果 require 参数字符串以“/”结尾,则示意加载的是一个位于绝对路径的模块文件,比方,require('/future/Demo/NodeJs/2. 模块化 /custom_module/tools.js')
将加载/future/Demo/NodeJs/2. 模块化 /custom_module/tools.js
;
2. 如果 require 参数以“./”或“../”结尾,那么则以相对路径的形式来查找模块,这种形式在利用中是最常见的,例如后面的例子中咱们用了 require('./custom_module/tools')
来加载;
3. 如果 require 参数不以“./”或“../”结尾,而该模块又不是外围模块,那么就要通过查找 node_modules
来加载模块了(应用 npm 获取的包通常就是以这种形式加载的);
举例来说:脚本 /future/Demo/NodeJs/2. 模块化 /app3.js
执行了 require('tools.js')
命令,Node 会顺次搜寻以下文件。
/usr/local/lib/node/tools.js
/future/Demo/NodeJs/2. 模块化 /node_modules/tools.js
/future/Demo/NodeJs/node_modules/tools.js
/future/node_modules/tools.js
/node_modules/tools.js
4. 如果指定的模块文件没有后缀,Node 会尝试为文件名增加 .js、.json、.node
后,再去搜寻。.js 件会以文本格式的 JavaScript 脚本文件解析,.json 文件会以 JSON 格局的文本文件解析,.node 文件会以编译后的二进制文件解析;
留神:外围模块领有最高的加载优先级,换言之如果有模块与其命名抵触,Node.js 总是会加载外围模块。
加载缓存
Node.js 模块不会被反复加载,这是因为 Node.js 通过文件名缓存所有加载过的文件模块,所以当前再拜访到时就不会从新加载了,留神,Node.js 是依据理论文件名缓存的,而不是 require() 提供的参数缓存的,也就是说即便你别离通过require('tools')
和 require('./node_modules/tools')
加载两次,也不会反复加载,因为只管两次参数不同,解析到的文件却是同一个。
包管理器:npm
npm 官网 https://www.npmjs.cn/
npm 是伴随 NodeJS 一起装置的包管理工具,能解决 NodeJS 代码部署上的很多问题,常见的应用场景有以下几种:
- 容许用户从 npm 服务器下载他人编写的第三方包到本地应用。
- 容许用户从 npm 服务器下载并装置他人编写的命令行程序到本地应用。
- 容许用户将本人编写的包或命令行程序上传到 NPM 服务器供他人应用。
应用 npm 命令装置模块,应用应用语法如下
npm install express // 本地装置
npm install express -g // 全局装置
本地装置
- 将安装包放在
./node_modules
下(运行 npm 命令时所在的目录),如果没有node_modules
目录,会在以后执行 npm 命令的目录下生成node_modules
目录。 - 能够通过 require() 来引入本地装置的包。
全局装置
- 将安装包放在
/usr/local
下或者你node
的装置目录。 - 能够间接在命令行里应用。
package.json 用于定义包的属性,接下来咱们来创立下:
$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help json` for definitive documentation on these fields
and exactly what they do.
Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
package name: (2. 模块化) test // 模块名
version: (1.0.0)
description: nodejs 模块化 demo // 我的项目形容
entry point: (app1.js)
test command:
git repository:
keywords:
author: wanwan
license: (ISC)
About to write to /xx/package.json:
{
"name": "test",
"version": "1.0.0",
"description": "nodejs 模块化 demo",
"main": "app1.js",
"dependencies": {"express": "^4.17.1"},
"devDependencies": {},
"scripts": {"test": "echo"Error: no test specified"&& exit 1"},
"author": "wanwan",
"license": "ISC"
}
Is this OK? (yes) yes
npm 罕用指令
npm version 查看模块版本
npm help 查看某条命令的具体帮忙
npm install 装置模块
npm uninstall 卸载模块
npm update 更新模块
npm outdated 查看模块是否曾经过期
npm ls 查看装置的模块
npm init 在我的项目中疏导创立一个 package.json 文件
四、参考资料
- Nodejs 开发指南.pdf
- Node 学习指南.pdf
- CommonJS 标准 — JavaScript 规范参考教程(alpha)
残缺示例代码:https://github.com/wanwan0306/future/tree/master/Demo/NodeJs/2. 模块化