一、写在后面

为了对立 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 代码部署上的很多问题,常见的应用场景有以下几种:

  1. 容许用户从 npm 服务器下载他人编写的第三方包到本地应用。
  2. 容许用户从 npm 服务器下载并装置他人编写的命令行程序到本地应用。
  3. 容许用户将本人编写的包或命令行程序上传到NPM服务器供他人应用。

应用 npm 命令装置模块,应用应用语法如下

npm install express      // 本地装置npm install express -g   // 全局装置

本地装置

  1. 将安装包放在 ./node_modules 下(运行 npm 命令时所在的目录),如果没有 node_modules 目录,会在以后执行 npm 命令的目录下生成 node_modules 目录。
  2. 能够通过 require() 来引入本地装置的包。

全局装置

  1. 将安装包放在 /usr/local 下或者你 node 的装置目录。
  2. 能够间接在命令行里应用。

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文件

四、参考资料

  1. Nodejs开发指南.pdf
  2. Node学习指南.pdf
  3. CommonJS标准 -- JavaScript 规范参考教程(alpha)

残缺示例代码:https://github.com/wanwan0306/future/tree/master/Demo/NodeJs/2.模块化