1 npm

Node.js 中的第三方模块又叫做包。
包是基于内置模块封装出来的,提供了更高级、更方便的 API,极大的提高了开发效率。
包和内置模块之间的关系,类似于 jQuery 和 浏览器内置 API 之间的关系。
npm, Inc. 公司提供了一个包管理工具
Node Package Manager(简称 npm 包管理工具)

1.1 安装第三方包

  1. npm i moment
  2. # 安装指定版本
  3. npm i moment@1.1.1
  4. # 一次性安装所有依赖,它会读取package.json的dependencies节点,然后进行安装
  5. npm i

node_modules 文件夹用来存放所有已安装到项目中的包。require() 导入第三方包时,就是从这个目录中查找并加载包。
package-lock.json 配置文件用来记录 node_modules 目录下的每一个包的下载信息,例如包的名字、版本号、下载地址等。
注意:今后在项目开发中,一定要把 node_modules 文件夹,添加到 .gitignore 忽略文件中。

1.2 包管理配置文件

package.json

  • 项目的名称、版本号、描述等
  • 项目中都用到了哪些包
  • 哪些包只在开发期间会用到
  • 那些包在开发和部署时都需要用到

快速创建

  1. npm init -y

执行命令时所处的目录中,快速创建 package.json

  • 上述命令只能在英文的目录下成功运行!所以,项目文件夹的名称一定要使用英文命名,不要使用中文,不能出现空格。
  • 运行 npm install 命令安装包的时候,npm 包管理工具会自动把包的名称和版本号,记录到 package.json 中。


1.3 dependencies 节点

image.png
dependencies 节点,专门用来记录使用 npm install 命令安装了哪些包。

—save 的意思是将模块安装到项目目录下,并在package文件的dependencies节点写入依赖。

  1. npm i module_name -S(--save)

默认就是带-S

1.4 卸载包

  1. npm uninstall 包名
  2. # 卸载全局包
  3. npm uninstall 包名 -g

npm uninstall 命令执行成功后,会把卸载的包,自动从 package.json 的 dependencies 中移除掉。

1.5 devDependencies节点

某些包只在项目开发阶段会用到,在项目上线之后不会用到,则把这些包记录到 devDependencies 节点中。
与之对应的,如果某些包在开发和项目上线之后都需要用到,则建议把这些包记录到 dependencies 节点中。

  1. npm i 包名 -D
  2. npm install 包名 --save-dev

1.6 切换镜像源

  1. # 查看镜像源
  2. npm config get registry
  3. # 切换镜像源
  4. npm config set registry=https://registry.npm.taobao.org
  5. # 通过nrm管理,安装nrm
  6. npm i nrm -g
  7. #查看可用镜像
  8. nrm ls

image.png

  1. # 切换
  2. nrm use taobao

1.7 包分类

npm - 图3核心依赖包:在开发期间和项目上线之后都会用到
开发依赖包:只在开发期间会用到
全局包:工具性质的包,类似 nrm,因为它们提供了好用的终端命令。

  1. npm i 包名 # 核心依赖包(会被记录到dependencies中)
  2. npm i 包名 -D # 开发依赖包(会被记录到devDependencies)
  3. npm i 包名 -g # 全局包

项目包又分为两类,分别是:

  • 开发依赖包(被记录到 devDependencies 节点中的包,只在开发期间会用到)
  • 核心依赖包(被记录到 dependencies 节点中的包,在开发期间和项目上线之后都会用到)

1.8 规范包结构

① 包必须以单独的目录而存在
② 包的顶级目录下要必须包含 package.json 这个包管理配置文件
③ package.json 中必须包含 name,version,main 这三个属性,分别代表包的名字、版本号、包的入口。

2 开发属于自己的包

2.1 创建目录

image.png
package.json (包管理配置文件)
index.js (包的入口文件)
README.md (包的说明文档)

2.2 定义package.json

  1. {
  2. "name": "kelliden-tools",
  3. "version": "0.0.1",
  4. "main": "index.js",
  5. "description": "格式化时间,html符号转换",
  6. "keywords": ["html", "data", "format"],
  7. "license": "ISC"
  8. }

license 是遵循开源许可协议

2.3 写功能

dataFormat.js:

  1. // 格式化时间
  2. function dataForma(date) {
  3. const dt = new Date(date);
  4. const y = addZero(dt.getFullYear());
  5. const m = addZero(dt.getMonth() + 1);
  6. const d = addZero(dt.getDay());
  7. const hh = addZero(dt.getHours());
  8. const mm = addZero(dt.getMinutes());
  9. const ss = addZero(dt.getSeconds());
  10. return `${y}年${m}月${d}日 ${hh}时${mm}分${ss}秒`
  11. }
  12. function addZero(n) {
  13. return n > 9 ? n : '0' + n;
  14. }
  15. module.exports = {
  16. dataForma
  17. }

htmlEscape.js:

  1. // 转译html字符
  2. function htmlEscape(htmlStr) {
  3. return htmlStr.replace(/<|>|"|&/g, match => {
  4. switch(match) {
  5. case '<':
  6. return '&lt;';
  7. case '>':
  8. return '&gt;';
  9. case '"':
  10. return '&quot;';
  11. case '&':
  12. return '&amp';
  13. }
  14. })
  15. }
  16. function unHtmlEscape(htmlStr) {
  17. return htmlStr.replace(/&lt;|&gt;|&quot;|&amp/g, match => {
  18. switch(match) {
  19. case '&lt;':
  20. return '<';
  21. case '&gt;':
  22. return '>';
  23. case '&quot;':
  24. return '"';
  25. case '&amp':
  26. return '&';
  27. }
  28. })
  29. }
  30. module.exports = {
  31. htmlEscape,
  32. unHtmlEscape
  33. }

index.js:

  1. const date = require('./src/dataFormat')
  2. const escape = require('./src/htmlEscape')
  3. module.exports = {
  4. ...date,
  5. ...escape
  6. }

2.4 发布与删除

到包的根目录

  1. nrm use npm # 切换回去
  2. npm login # 登录
  3. npm publish # 发布
  4. npm unpublish kelliden-tools --force # 删除

3 模块加载机制

3.1 优先从缓存中加载

模块在第一次加载后会被缓存。
这也意味着多次调用 require() 不会导致模块的代码被执行多次。
注意:不论是内置模块、用户自定义模块、还是第三方模块,它们都会优先从缓存中加载,从而提高模块的加载效率。

3.2 内置模块加载机制

内置模块是由 Node.js 官方提供的模块,内置模块的加载优先级最高。
例如,require(‘fs’) 始终返回内置的 fs 模块,即使在 node_modules 目录下有名字相同的包也叫做 fs。

3.3 自定义模块的加载机制

使用 require() 加载自定义模块时,必须指定以 ./ 或 ../ 开头的路径标识符。
在加载自定义模块时,如果没有指定 ./ 或 ../ 这样的路径标识符,则 node 会把它当作内置模块或第三方模块进行加载。

同时,在使用 require() 导入自定义模块时,如果省略了文件的扩展名,则 Node.js 会按顺序分别尝试加载以下的文件:

  • ① 按照确切的文件名进行加载
  • ② 补全 .js 扩展名进行加载
  • ③ 补全 .json 扩展名进行加载
  • ④ 补全 .node 扩展名进行加载 ⑤ 加载失败,终端报错

3.4 第三方模块的加载机制

如果传递给 require() 的模块标识符不是一个内置模块,也没有以 ‘./’ 或 ‘../’ 开头,则 Node.js 会从当前模块的父 目录开始,尝试从 /node_modules 文件夹中加载第三方模块。

如果没有找到对应的第三方模块,则移动到再上一层父目录中,进行加载,直到文件系统的根目录。
image.png

3.5 目录作为模块

当把目录作为模块标识符,传递给 require() 进行加载的时候,有三种加载方式:

  • ① 在被加载的目录下查找一个叫做 package.json 的文件,并寻找 main 属性,作为 require() 加载的入口
  • ② 如果目录里没有 package.json 文件,或者 main 入口不存在或无法解析,则 Node.js 将会试图加载目录下的 index.js 文件。
  • ③ 如果以上两步都失败了,则 Node.js 会在终端打印错误消息,报告模块的缺失:Error: Cannot find module ‘xxx

    -. 常用npm包

    -.1 时间格式化包moment

    ```javascript const moment = require(‘moment’);

const dt = moment().format(‘YYYY年MM月DD日 HH时mm分ss秒’);

console.log(dt);

  1. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1688721/1624331454623-071b0d76-cacc-41e0-b099-b7f13c41c699.png#align=left&display=inline&height=45&margin=%5Bobject%20Object%5D&name=image.png&originHeight=90&originWidth=1126&size=21918&status=done&style=none&width=563)
  2. <a name="RmizU"></a>
  3. ## -.2 自动重启项目 nodemon
  4. ```shell
  5. # 安装
  6. sudo npm i -g nodemon
  7. # 使用
  8. nodemon app.js

代码被修改之后,会被 nodemon 监听到,从而实现自动重启项目的效果。