一、写在后面
为了对立 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.jsconst 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.jsconst http = require('http');const { calculate, getUrl } = require('tools'); // node_modulesconst 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 initThis 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 fieldsand exactly what they do.Use `npm install <pkg>` afterwards to install a package andsave 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: wanwanlicense: (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.模块化