为了统一 Javascript 在浏览器以外的实现,CommonJS 诞生了,CommonJS 试图定义一套普通应用程序使用的 API,从而填补 JavaScript 标准库过于简单的不足。 CommonJS 规范包括了模块、包、系统、控制台、文件系统、单元测试等部分。javascript
Node.js 是目前 CommonJS 规范最热门的一个实现,随着 CommonJS 规范的更新,Node.js 也在不断跟进 ,但 Node.js 并不彻底遵循 CommonJS 规范。这是全部规范制定者都会遇到的尴尬局面,由于规范的制定老是滞后于技术的发展。html
模块(Module)和包(Package)是 Node.js 最重要的支柱,开发一个具备必定规模的程序不可能只用一个文件,一般须要把各个功能拆分、封装,而后组合起来,模块正是为了实现这种方式而诞生。
在浏览器 JavaScript 中,脚本模块的拆分和组合一般使用 HTML 的 script 标签来实现。Node.js 提供了 require 函数来调用其余模块,并且模块都是基于文件的,换句话说就是每一个文件都是一个模块,机制十分简单。java
nodejs的模块能够分为两类,一类是核心模块,另外一类是文件模块。node
核心模块是 nodejs 官方提供的,node 进程启动时,部分核心模块就被直接加载进内存中, 因此这部分核心模块咱们就能够直接经过require 进行引入。好比 http 模块、url 模块、fs 模块等。git
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
文件夹。github
按路径加载模式express
// 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文件夹加载模式npm
// 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
;json
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 是随同 NodeJS 一块儿安装的包管理工具,能解决 NodeJS 代码部署上的不少问题,常见的使用场景有如下几种:
使用 npm 命令安装模块,使用使用语法以下
npm install express // 本地安装 npm install express -g // 全局安装
本地安装
./node_modules
下(运行 npm 命令时所在的目录),若是没有 node_modules
目录,会在当前执行 npm 命令的目录下生成 node_modules
目录。全局安装
/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文件
完整示例代码:https://github.com/wanwan0306/future/tree/master/Demo/NodeJs/2.模块化