> For the complete documentation index, see [llms.txt](https://lizh.gitbook.io/knowledge/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lizh.gitbook.io/knowledge/nodejs/04npm-cong-ling-kai-shi-kai-fa-yi-ge-ruan-jian-bao.md).

# NPM：从零开始，开发一个软件包

[npm](https://www.npmjs.com/) (Node Package Manager) 本来是 Node.js 的包管理工具，但随着JS这几年的蓬勃发展，现在 npm 已经成为了几乎所有跟 JS 相关的工具和软件包的管理工具，并且还在不断的发展完善中。

现在最新版的 Node.js 的安装都会自带npm，装上Node.js就可以使用npm。

### 初始化项目

发布一个 npm 代码包，本质上就是将你的代码公开在 `https://www.npmjs.com/` 网上。使用者可以通过 `npm install [npm包名]`，来引入你的代码。关键在于两点：

* 输出的 Js 文件，也就是代码主体。如：通常输出到\`\`lib/index.js\`。
* `package.json` 配置中指明你的输出文件的位置。这个是通过`main`属性来指定的

初始化项目，就是要创建一个 `package.json` 文件，其中模块的名字和版本号是必填项。可以手动创建，也可以用 `npm init` 自动创建。

`package.json`部分字段说明：[package.json参数详解](https://www.jianshu.com/p/0863270e14d4)

```json
{
  name: '', //插件的名字
  version: '', //插件版本号
  description: '', //插件描述
  author: '', //作者名
  main: '', //入口文件路径，require(name)将根据这个路径来引入
  files: '', //文件夹名，所有文件都会被包含进项目中(除非是那些在其他规则中被忽略的文件)
  bin: {}, //许多包有一个或多个可执行文件希望被安装到系统路径。提供一个bin字段，它是一个命令名和本地文件名的映射。在安装时，如果是全局安装，npm将会使用符号链接把这些文件链接到prefix/bin，如果是本地安装，会链接到./node_modules/.bin/。
  keywords: '', //关键词，使用数组形式，方便npm官网搜索
  scripts: {}, //命令行，通过npm run 执行
  license: '', //许可证书，一般开源是MIT
  homepage: '', //项目主页的url
  repository: '', //github仓库项目地址
}
```

![image-20201103231118837](https://my-files-1259410276.cos.ap-chengdu.myqcloud.com/md_images/image-20201103231118837.png)

### 开发

这个可以很灵活，具体开发取决由 npm 包的复杂度。

* 可以是简单的，直接在`lib`文件夹下，创建一个只有一行代码的`console.log(Hello World!)`的`JS`文件；也可以采用`webpack + vue`之类的框架，开发一个复杂的项目，将最终编译出来的`JS`文件输出到`lib`文件夹。
* 可以给项目加`eslint`等代码校验
* 编写测试模块，如：`mocha` 和 `chai`
* 可以用`gitlab CI`类的方式实现自动化部署
* 可以创建`readme.md`文档，编写使用说明

### 测试

**相对路径安装**

进入测试项目目录，用相对路径安装包。安装完后，可以在 `node_modules` 文件夹检查是否安装成功。

```
cd [项目目录]
npm install [包的相对路径]
```

**npm link 测试**

**相对路径安装**找路径比较麻烦，所以我们推荐使用 `npm link` 将 npm 包链接到全局，再安装到本地项目。

首先，定位到 npm 包项目的目录下，运行 `npm link`。

```shell
cd [npm包项目]
npm link
# 执行后，输出/usr/local/lib/node_modules/[插件项目名称] -> /Users/${whoami}/Documents/[插件项目路径]/[插件项目名称]
```

意思是将 **npm包项目** 连接到全局的 `node_modules` 下（全局 `node_modules` 目录下可以看到该 npm 包）。

然后，定位到需要测试项目，运行 `npm link [package-name]`，将 npm 包安装到当前项目。npm 包的修改，在 build 后，会同步更新到当前项目的 `node_modules`。

```shell
cd [需要使用 npm 包的项目目录]
npm link [package-name]
# /Users/[whoami]/Documents/[project-path]/node_modules/[package-name] -> /usr/local/lib/node_modules/[package-name] -> /Users/[whoami]/Documents/[project-path]/[package-name]
```

测试完成后，在 npm 包项目取消连接：

```
cd [npm包项目]
npm unlink
```

### 发布

* 注册：`npm adduser`
* 判断是否登录：`npm whoami`
* 登录：`npm login`
* 发布：`npm publish`。每次发布，必须修改版本号。版本号更新，要遵循 `Semver(语义化版本号)` 规范：
  * 升级补丁版本号：npm version patch
  * 升级小版本号：npm version minor
  * 升级大版本号：npm version major
* 删除：\*\*根据规范，只有在发包的24小时内才允许撤销发布的包。\*\*即使是你删除了，也只是无法被搜索到，仍可以通过链接直接访问。

  ```shell
  npm unpublish --force
  ```

### 使用

安装：`npm install [npm包名]`

使用：`import "[npm包名]`或者`import Obj, {Obj1, Obj2} from 'npm包名'`

### 权限转让

要使用 CLI 将软件包传输给另一个 npm 用户，请依次运行 `npm owner add` 和 `rm` 命令。

```shell
npm owner add <their-username> <package-name>
npm owner rm <your-username> <package-name>
```

如果您为写入启用了双重身份验证，则将一次性密码添加到参数 --otp：

```shell
# 其中123456是来自身份验证器应用程序的代码
npm owner add <their-username> <package-name> --otp=123456
npm owner rm <your-username> <package-name> --otp=123456
```

### 相关问题

#### npm link 失败

**实际场景一：** 将正在开发的 npm 包，通过 npm link 引入业务项目中调试时报错：

```shell
Module build failed: TypeError: Invalid PostCSS Plugin found at: plugins[0]
```

原因是包所在的项目中的 postcss 配置文件中的一些插件，在业务项目中没有安装。

**解决方法：** 一是修改 npm 包项目的 postcss 配置文件；二是业务项目中，忽略项目外的配置文件。

**实际场景二：** node 版本原因。

如果使用类似 nvm 的 Nodejs 的版本管理器，默认情况下，nvm 会为您安装的每个节点版本创建一个不同的全局 node\_modules 文件夹。

运行时 npm link，将使用项目中使用的特定版本的节点来创建链接，这意味着只有使用相同版本节点的项目才能访问本地版本的依赖项。**更令人沮丧的是，npm link 在发生这种情况时不会抛出错误。**

**解决方法：** 在开发的 npm 包项目和业务项目，运行 `nvm use` 命令，使用相同的 Nodejs 版本。注意：即使用 node -v 命令查看，两个项目的 Nodejs 版本是相同的，也建议重新指定下相同版本。

**实际场景三：** 如果业务项目运行 npm i 安装了其他包，需要重新运行 npm link \[package-name]。

#### npm publish报错

报错`[no_perms] Private mode enable, only admin can publish this module [no_perms] Private mode enable, only admin can publish this module`

\*\*出现原因：\*\*使用的是淘宝源`cnpm`，登陆到的是`npm`

\*\*解决方法：\*\*切换到 `npmjs` 的网址，代码如下：`npm config set registry http://registry.npmjs.org/`。也可以用nrm管理源。

### 参考资料

[Why Your npm link Commands Might Be Failing](https://dev.to/rubengmurray/why-your-npm-link-commands-might-be-failing-4ncj)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lizh.gitbook.io/knowledge/nodejs/04npm-cong-ling-kai-shi-kai-fa-yi-ge-ruan-jian-bao.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
