6. Node 之 包 与 npm

166 阅读11分钟

一、包的概念

1. 什么是包

Node.js 中的 第三方模块 又叫做

就像 电脑计算机 指的是相同的东西。 第三方模块 指的是同一个概念,只不过叫法不同。

2. 包的来源

不同于 Node.js 中的内置模块与自定义模块。包是由第三方个人或团队开发出来的。免费供所有人使用。

注意:Node.js 中的包都是免费且开源的,不需要付费即可免费下载使用。

3. 为什么需要包

由于 Node.js 的内置模块仅提供了一些底层的 API, 导致在基于内置模块进行项目开发时,效率很低。

包是基于内置模块封装出来的,提供了更高级、更方便的API,极大的提高了开发效率

内置模块之间的关系,类似于 **jQuer**y 和 浏览器内置 API 之间的联系。

4. 从哪里下载包

国外有一家 IT 公司,叫做 npm, lnc. 这家公司旗下有一个非常著名的网站: www.npmjs.com/, 它是全球最大的包共享平台,可以从这个网站上搜索到任何我们需要的包,只要我们有足够的耐心!

npm, lcn公司提供了一个地址为 registry.npmjs.org/ 的服务器, 来对外共享所有的包,我们可以从这个服务器上下载自己所需要的包。

注意

5. 如何下载包

npm, lnc 公司提供了一个 包管理工具,我们可以使用这个包管理工具,从 registry.npmjs.org/ 服务器把需要的包下载到本地使用。

这个包管理工具的名字叫做 Node Package Manager(简称 npm 包管理工具),这个包管理工具随着 Node.js 的安装包一起安装到了用户的电脑上。

我们可以在终端中执行 npm -v 命令,来查看自己电脑上所安装的 npm 包管理工具的版本号:

image.png

二、npm 与 包

1. npm 初体验

我们用来格式化时间

格式化时间的传统做法:

  1. 创建格式化时间的自定义模块
  2. 定义格式化时间的方法
  3. 创建补0 函数
  4. 从自定义模块中导出格式化时间的函数
  5. 导入格式化时间的自定义模块
  6. 调用格式化时间的函数

image.png

格式化时间的高级做法

  1. 使用 npm 包管理工具,在项目中安装格式化时间的包 moment
  2. 使用 require() 导入格式化时间的包
  3. 参考 moment 的官方 API 文档对时间进行格式化

image.png

2. 在 项目中安装 包的命令

安装指定名称的包:

npm i 包的完整名称

// 例子:
npm i moment

包装指定版本的包

默认情况下,使用 npm i 命令安装包的时候,会自动安装最新版本的包。如果需要安装指定版本的包,可以在包名之后 ,通过 @ 符号 指定具体的版本,例如:

npm i moment@2.22.2

3. 导入需要的包

导入需要的包,导入的名称,就是下载包时的包的名称

// 导入的名称,就是下载包时的包的名称
const moment = require('moment');

// 安装时
npm i moment

4. 初次安装包后多了哪些文件

初次装包完成后,在项目文件夹下多了一个叫做 node_modules 的 文件夹 和 package-lock.json 的配置文件。

其中:

node_modules 文件夹 用来存储所有已安装到项目的包require() 导入第三方时,就是从这个目录中查找并加载包的。

package-lock.json 配置文件 用来记录 node_modules 目录下的每一个包的下载信息、例如包的名字、版本号、下载地址等。

注意:我们不要手动修改node_modules 或 package-lock.json 文件夹中的任何代码,npm 包管理工具会自动维护它们。

5. 包的语义版本规范

包的版本号是以 “点分十进制” 形式进行定义的,总共有三位数字,例如 2.24.0

其中每一位数字所代表的含义如下

第 1 位数字: 大版本
第 2 位数字: 功能版本
第 3 位数字: Bug 修复版本

版本提升号的规则:只要前面的版本号增长了,则后面的版本号 归零。 例如,2.24.1 版本 改了下功能版本,能就变成 2.25.0, 例如 2.25.0 版本进行了大版本的修改,则变成了 3.0.0

三、package.json

1. 包管理配置文件 package.json

npm 规定,在 项目录根目录 中, 必须 提供一个叫做 package.json 的包管理配置文件。用来记录与项目有关的一些配置信息。例如:

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

2. 多人协作的问题

遇到的问题:如下所示:项目中的 第三方包的体积过大,不方便团队成员之间共享项目代码。

解决方案:共享时 剔除 node_modules.

image.png image.png

3. package.json 作用

项目根目录 中, 创建了一个叫做 package.json 的配置文件,用来记录项目中安装了哪些包, 从而方便剔除 node_modules 目录之后 ,在默认成员之间共享项目的源代码。

注意:今后在项目开发中,一定要把 node_modules 文件夹,添加到 .gitgnore 忽略文件中。

4. 快速创建 package.json

npm 包管理工具提供了一个 快速命令,可以在 **执行命令时所处的目录**中,快速创建 package.json 这个包管理配置文件。

npm init -y

image.png

注意

  1. 上述命令 只能在英文的目录下 成功运行 !所以,项目文件夹的名称一定要使用英文名,不要使用中文名,且不能出现空格

  2. 运行 npm i 命令安装包的时候, npm 包管理工具会自动把 包的名称 和版本号,记录到 package.json 中。

5. package.json 中的 dependencies 节点

package.json 文件中,有一个 dependencies 节点,专门用来记录我们使用 npm i 命令安装了哪些包。

image.png

6. package.json 中 devDependencies 节点

如果某些包 只在项目开发阶段 会用时,在 项目上线之后不会用到,则建议把这些包记录到 devDependencies 节点中

与之对应的,如果某些包在 开包和项目上线之后 都需要用到,则建议把这些包记录 到 devpendencies 节点中。

可以使用如下命令,将包记录到 devDependencies 节点中:

// 安装指定的包,并记录到 devDependencies 节点中
npm i 包名 -D

// 上面等价于
npm install 包名 --save-dev

7. 一次性安装所有的包

当我们拿到一个 剔除了 node_modules 的项目之后 ,需要先把所有的包下载到项目中, 才能将项目运行起来,否则会报类似下南的错误。

image.png

这时可以运行 npm i 一次性安装所有的依赖包

npm i

8. 卸载包

可以运行 npm unistall 命令,来卸载指定的包:

npm uninstall moment

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

image.png

image.png

四、下载包相关

1. 为什么下包速度慢

在使用 npm 下包的时候,默认从国外的 registry.npmjs.org/ 服务器进行下载,此时,网络数据的传输需要经过漫长的海底光缆,因此下包速度会很慢。

image.png

2. 切换下包镜像源

下包的镜像源,指的就是 下包的服务器地址

# 查看当前的下包镜像源
npm config get registry

# 将下包的镜像源切换为淘宝镜像源
npm config set registry=https://registry.npm.taobao.org/

# 检查镜像源是否下载成功
npm config get registry

3. nrm 查看、切换镜像源

为了更方便的切换下包的镜像源,我们可以安装 nrm 这个小工具, 利用 nrm 模块提供的终端命令,可以快速查看和切换包的镜像源。

# 通过 npm 包管理器, 将 nrm 安装为全局可利用的工具
npm i nrm -g 

# 查看所有可用的镜像源
nrm ls

# 将下载的镜像源切换 为 taobao 镜像
nrm use taobao

4. 包的分类

a. 包的两大类

使用 npm 包管理工具下载的包,共分为两大类: 分别是

  • 项目包
  • 全局包
b. 项目包

那些被安装到 项目的 node_modules 目录中 的包,都是项目包。

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

  • 开发依赖包(被记录到 devDependencies 节点中的包,只在开发期间会用到)

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

npm i 包名 -D # 开发依赖包,会被记录到 devDependencies 节点下
npm i 包名    # 核心依赖包,会被记录到 dependencies 节点下
c. 全局包

在 执行 npm install 命令时,如果提供了 -g 参数,则会把包安装为 全局包

全局包会被包装到 C:\Users\用户目录\AppData\Roaming\npm\node_modules 目录下

npm i 包名 -g    # 全局安装指定的包
npm uninstall 包名 -g  # 卸载全局安装的包

注意:

  1. 只有 工具性质的包,才有全局安装的必要性。因为它们提供了好用的终端命令。
  2. 判断某个包是否需要全局安装后才能使用,可以 参考官方提供的使用说明 即可。

5. 规范的包结构

在清楚了包的概念,以及如何下载和使用之后 ,深入了解一下包的内部结构

一个规范的包,它的组成结构,必须符合以下 3 点要求

  1. 包必须以 单独的目录 而存在

    image.png
  2. 包的顶级目录下必须包含 package.json 这个包管理配置文件

image.png
  1. package.json 中必须包含 name、version、main 这三个属性,分别代表 包的名字、版本号、包的入口

image.png

五、发布包

1. 开发属性自己的包

我们想要实现一个 能够格式化时间、把 html 进行转义字符串,同时也能把 html 转义后的字符串还原回来 的功能。

包的目录如下:

image.png

a. 初始化包的基本结构
  1. 新建 node-tools 文件夹,作为 包的根目录
  1. 在 node-tools 文件夹,新建如下三个文件:
  • package.json (包管理配置文件)
  • index.js (包的入口文件)
  • README (包的说明文档)
b. 初始化 package.json 文件
{
    // 包的名称
    "name": "node-learn-tools",
    // 包的版本
    "version": "1.0.0",
    // 包的入口文件
    "main": "index.js",
    // 包的描述
    "description": "时间格式、html转义包",
    // 包的搜索关键诩
    "keyword": ["date", "html"],
    // 包的许可协议,默认用 ISC
    "license": "ISC"
}
c. 在 src\dateFormat.js 中定义格式时间的方法
# dateFormat.js

// 格式化时间的方法
function dateformDate(dateStr) {
    const dt = new Date(dateStr);

    const y = dt.getFullYear();
    const m = padZero(dt.getMonth() + 1);
    const d = padZero(dt.getDate());

    const hh = padZero(dt.getHours());
    const mm = padZero(dt.getMinutes());
    const ss = padZero(dt.getSeconds());

    return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}

// 补 0
function padZero(n) {
    return n > 9 ? n : `0${n}`
}

module.exports = {
    dateformDate
}
d. 在 src\htmlEscape.js 中定义 html 转义及还原 的方法
# htmlEscape.js

// 定义转义 html 字符串的方法
function htmlEscape(htmlStr) {
    return htmlStr.replace(/<|>|"|&/g, (match) => {
        switch(match) {
            case "<":
                return "&lt;"
            case ">":
                return "&gt;"
            case '"':
                return "&quot;"
            case '&':
                return "&amp;"
        }
    })
}

// 定义还原 html 的方法
function htmlUnEscape(htmlStr) {
    return htmlStr.replace(/&lt;|&gt;|&quot;|&amp;/g, (match) => {
        switch(match) {
            case "&lt;":
                return "<"
            case "&gt;":
                return ">"
            case '&quot;':
                return '"'
            case '&amp;':
                return "&"
        }
    })
}

module.exports = {
    htmlEscape, 
    htmlUnEscape
}
e. 在 index.js, 导入两个模块

在 index.js, 导入两个模块, 得到需要向外共享的方法, 使用 module.exports 把对应的方法共享出去

# index.js

const date = require('./src/dateFormat')
const escape = require('./src/htmlEscape')

module.exports = {
    ...date,
    ...escape
}
f. README.md 文件的作用

包的说明文档 README.md,如果按照规范的格式进行书写,到时候包发布到 npm 官网上就是呈现如下的效果:

image.png
g. 编写包的说明文档 README.md

包根目录中的 README.md 文件,是 包的使用说明文 档。通过它,我们可以事先把包的使用说明, 以及 markdown 的格式写出来,方便用户参考。

README.md 文件中具体写什么内容, 没有强制的要求,只要能够清晰的把包的作用、用法、注意事项等描述清楚即可。

我们所创建的这个包的 README.md 文档中,会包含以下 6 项内容: 安装方式、导入方式、格式化时间、转义 HTML 中的特殊字符、还原 HTML 中的特殊字符,开源协议。

image.png

2. 注册 npm 账号

  1. 访问 www.npmjs.com/ 网站,点击 sign up 按钮,进入注册页面
  2. 填写账号相关信息: fullName、Username、Password
  3. 点击 Create an Account 按钮,注册账号
  4. 登录邮箱, 点击验证链接,进行账号的验证。

3. 登录 npm 账号

npm 账号注册完成后,可以在终端中进行 npm login 命令,依次输入 用户名、密码、邮箱号、即可登录成功。

注意:运行 npm login 命令之前,必须先把 下包的镜像源切换到 npm 的官网上不能再使用淘宝或其他镜像源

image.png

4. 把包发布到 npm 上

终端 切换到包的根目录之后 ,运行 npm publish 命令,即可将包发布到 npm 上。

注意: 包名不能雷同

image.png

5. 去 npm 上查看已发布的包

image.png image.png

6. 删除已发布的包

运行 npm unpublish 包名 --force 命令,即可从 npm 删除已发布的包

npm unpublish 包名 --force

注意:

  1. npm unpublish 命令只能 删除 72 小时以内 发布的包
  2. npm unpublish 删除的包,在 24 小时内不允许 重复发布
  3. 发布包的时候慎重,尽量不要往 npm 上发布没有意义的包 !

image.png