文章目录
  1. 1. 0. 创建
  2. 2. 1. 准备
  3. 3. 2. 发布
    1. 3.1. 2.0. 修正下载源
    2. 3.2. 2.1. 创建并登录 npmjs.org 账户
  4. 4. 3. 真正的开始
    1. 4.1. 3.1. 合理的 package.json
    2. 4.2. 3.2. scripts 字段
    3. 4.3. 3.3. Git 设置
    4. 4.4. 3.4. NPM 包文件设置
    5. 4.5. 3.5. 配置 tsconfig.json
    6. 4.6. 3.6. 使用 tslint.json
  5. 5. 4. 维护
    1. 5.1. 4.1. 版本号维护
    2. 5.2. 4.2. 使用标签
    3. 5.3. 4.3. 使用前缀

本文介绍如何发布一个包到 npmjs.org,包括创建、发布、撤回、更新、使用分支等等,以及其中
包含的一些小技巧。

0. 创建

创建一个包很简单,就是手动或者用 npm init 命令直接生成一个 package.json 文件,一个
包就算是创建出来了。剩下的就是给它添加内容而已了。

如果使用 npm init 命令配合 -y 或者 --yes 参数,可以不使用命令行交互模式,而
快速地创建一个 package.json 文件。

1
npm init -y

比如我这里创建出来的是:

name 字段默认是当前所在的目录名称。

1
2
3
4
5
6
7
8
9
10
11
12
{
"name": "test",
"version": "0.1.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "Angus.Fenying <i.am.x.fenying@gmail.com> (https://fenying.net/)",
"license": "Apache-2.0"
}

什么,你说你创建出来是下面这样的?有些字段的初始值和我的不一样?

1
2
3
4
5
6
7
8
9
10
11
12
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}

别急,那是因为你没有设置 NPM 的一些默认配置。通过下面三条命令,可以设置创建新的 NPM
包时使用的默认属性。

1
2
3
4
5
npm config set init-author-name "Angus.Fenying"             # 你的名称
npm config set init-author-email "i.am.x.fenying@gmail.com" # 你的邮箱
npm config set init-author-url "https://fenying.net" # 你的个人网页
npm config set init-license "Apache-2.0" # 开源授权协议名
npm config set init-version "0.1.0" # 版本号

1. 准备

现在你可以为 package.json 添加内容了,比如修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"name": "npm-tutorial-test-1",
"version": "0.1.0",
"description": "This is a test package for my NPM tutorial.",
"main": "index.js",
"scripts": {
"test": "echo hello"
},
"keywords": [
"test"
],
"author": "NPM Learner <me@sample.com> (https://sample.com/)",
"license": "MIT"
}

然后添加一个 README.md 文件,内容如下:

1
2
3
4
5
6
7
# NPM Tutorial Test 1

This is a test package for my NPM tutorial.

## License

This package is published under [MIT license](./LICENSE).

添加你的 LICENSE 文件(开源协议),以及一个 index.js 文件。

现在,一个最基本的包就是准备好了,等待发布了。

2. 发布

既然包已经准备好了,那么就可以发布了。

2.0. 修正下载源

如果你曾经为了加速 NPM 下载速度而修改了它的下载源,那么请改回去,不然是无法发布的。

检查方式:

1
npm config get registry

NPM 的官方源是 https://registry.npmjs.org/,如果你看到控制台打印是这个,那么就没
问题了。而如果不是,那么请使用下面的命令修改回去:

1
npm config set registry https://registry.npmjs.org/

2.1. 创建并登录 npmjs.org 账户

如果你没有 npmjs.org 账户,那么先要创建一个,方法很简单:

1
npm adduser

根据提示创建即可。

记得验证邮箱,否则将无法发布包。

如果已经有 npmjs.org 账户了,请直接登录:

1
npm login

3. 真正的开始

上面的教程只是一个最简单的 DEMO,远远不能满足我们的发布需要,下面以一个需要编译的
TypeScript 包为例,看看如何发布和管理。

3.1. 合理的 package.json

先来看一个 package.json 的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
{
"name": "full-sample",
"version": "0.1.0",
"description": "A sample to learn NPM.",
"main": "./dist/index.js",
"scripts": {
"prepare": "npm run rebuild",
"build": "tsc -p .",
"rebuild": "npm run clean && npm run lint && npm run build",
"test": "echo See directory sources/tests",
"clean": "rm -rf dist",
"lint": "tslint --project tslint.json"
},
"keywords": [
"npm",
"sample"
],
"author": "NPM Learner <me@sample.com> (https://sample.com/)",
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "git+https://github.com/learn-npm/full-sample.git"
},
"bugs": {
"url": "https://github.com/learn-npm/full-sample/issues"
},
"homepage": "https://github.com/learn-npm/full-sample#readme",
"types": "./dist/index.d.ts",
"typings": "./dist/index.d.ts",
"dependencies": {
"sequelize": "^4.24.0"
},
"devDependencies": {
"@types/node": "^8.0.51",
"@types/sequelize": "^4.0.79",
"typescript": "^2.6.1"
},
"engines": {
"node": ">=8.0.0"
}
}

假定项目的 TypeScript 源代码都在 sources 目录,编译结果都在 dist 目录。

上面与 DEMO 有什么区别呢?下面逐个字段解释:

  • homepage

    指定项目的主页地址,如果没有一般可以使用项目的 GitHub 地址。

  • bugs.url

    指定项目的 Bug 反馈地址,一般可以用项目的 GitHub Issue 地址。

  • repository.urlrepository.type

    指定项目的源码仓库地址,可以指定是 git/cvs/svn。

  • main

    指定 Node.js 中 require(“moduel-name”) 导入的默认文件。

  • keywords

    指定项目的关键词,合理设置有利于让他人发现你的项目。

  • engines

    设置项目对引擎的版本要求,比如 node、electron、vscode 等。

  • typestypings

    设置项目内置的 TypeScript 模块声明文件入口文件。

3.2. scripts 字段

scripts 字段作为单独一节解释,因为它是用于构建控制和发布控制的工具。

  • scripts.build

    这个允许使用 npm run build 命令直接编译 TS 代码。

  • scripts.lint

    这个允许使用 npm run lint 命令调用 TSLinter 对代码进行格式检查。

  • scripts.clean

    这个允许使用 npm run clean 命令清理编译结果。

  • scripts.rebuild

    这个允许使用 npm run rebuild 命令清理编译结果然后重新生成。

  • scripts.prepare

    这个不是给我们用的,而是 NPM 提供的钩子,这个命令会在执行 npm publish 的时候
    被调用。因此可以用这个钩子进行发布前构建。

3.3. Git 设置

Git 应当使用 .gitignore 文件忽略那些编译结果,以及 NPM 依赖的包文件:

1
2
3
/node_modules/
/dist/
*.log

3.4. NPM 包文件设置

NPM 打包发布的时候,会默认把当前目录下所有文件打包。但是 Git 仓库中,有些东西是不需要
发布到 NPM 的,因此我们需要使用一个文件 .npmignore 来忽略这些文件,常用配置如下:

1
2
3
4
5
6
7
8
9
/.git/
/.vscode/
/docs/
/node_modules/
.gitignore
.npmignore
tslint.json
tsconfig.json
*.log

这些文件都不是发布需要的内容,因此可以忽略。

3.5. 配置 tsconfig.json

前面说了,假定 TypeScript 的代码在 sources 目录下,编译的输出目录则为 dist。那么需要
在 tsconfig.json 里面通过 rootDiroutDir 选项指定。

其次,为了让其它 TypeScript 程序能正常使用你的包,你还应该设置 declaration 字段为
true,使之自动生成 *.d.ts 文件。此处我们假定模块的入口是 index.js ,因此你必须
实现一个 index.ts 文件,作为模块的入口。

另外,如果要实现 TypeScript 源码调试,则需要开启 sourceMap 选项,以生成源码映射
文件。

3.6. 使用 tslint.json

现在,就可以愉快地编写代码了吗?不不不,为了规范代码,我们还需要配置下 TSLinter。通过
下面的命令初始化一个 tslint.json 文件。

1
2
npm install tslint -g
tslint --init

TS Linter 的规则非常多,而且默认规则限制非常严格,可以适当根据提示解除一些限制。比如
作者就采用了如下配置,仅供参考:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
"defaultSeverity": "error",
"extends": [
"tslint:recommended"
],
"jsRules": {
},
"rules": {
"interface-name": false,
"trailing-comma": false,
"max-classes-per-file": false,
"ordered-imports": false,
"variable-name": false,
"prefer-const": false,
"member-ordering": false,
"no-bitwise": false,
"forin": false,
"object-literal-sort-keys": false,
"one-line": [false],
"object-literal-key-quotes": [false],
"no-string-literal": false,
"no-angle-bracket-type-assertion": false,
"only-arrow-functions": false,
"no-namespace": false,
"no-internal-module": false,
"unified-signatures": false,
"ban-types": false,
"no-conditional-assignment": false,
"radix": false
},
"rulesDirectory": []
}

如果想在 Visual Studio Code 里面实现 TS Linter 智能提示,则还需要安装 VSCode 的
TSLint 扩展。

现在,可以尽情地编写代码了。

4. 维护

4.1. 版本号维护

维护一个包,肯定是要进行包的版本升级的。如何进行呢?手动修改 package.json 的 version
字段是一个办法,但是显得有点 low。可以使用下面的命令:

1
2
3
4
npm version v0.1.0      # 版本号变成 0.1.0,即显式设置版本号。
npm version patch # 版本号从 0.1.0 变成 0.1.1,即修订版本号加一。
npm version minor # 版本号从 0.1.1 变成 0.2.0,即子版本号加一。
npm version major # 版本号从 0.2.0 变成 1.0.0,即主版本号加一。

但是,除此之外,还有四条命令,用于创建“预发布版本”,也就是非稳定版本。

1
2
3
4
5
6
7
8
9
10
11
12
13
npm version v1.2.3

# 版本号从 1.2.3 变成 1.2.4-0,就是 1.2.4 版本的第一个预发布版本。
npm version prepatch

# 版本号从 1.2.4-0 变成 1.3.0-0,就是 1.3.0 版本的第一个预发布版本。
npm version preminor

# 版本号从 1.2.3 变成 2.0.0-0,就是 2.0.0 版本的第一个预发布版本。
npm version premajor

# 版本号从 2.0.0-0 变成 2.0.0-1,就是使预发布版本号加一。
npm version prerelease

注意:
version 命令默认会给你的 git 仓库自动 commit 一把,并打一个 tag。如果不想它动你的
git 仓库,你应该使用 --no-git-tag-version 参数,例如:

1
npm --no-git-tag-version version patch

如果你想一劳永逸,那么可以使用如下 NPM 设置彻底禁止它:

1
2
npm config set git-tag-version false  # 不要自动打 tag
npm config set commit-hooks false # 不要自动 commit

4.2. 使用标签

以 TypeScript 为例,通过 npm info typescript 可以看到 dist-tags 字段有着五个
值,分别是 latest, beta, rc, next, insiders,这些都是 dist-tag,可以
称之为标签——你可以把它理解为 git 里面的分支。

有什么用呢?其实,我们平时用 npm install xxxxxx 的时候,是使用了一个潜在的选项
tag = latest,可以通过 npm config list -l | grep tag 看到。

因此实际上是执行了 npm install xxxxxx@latest。也就是安装了 latest 这个标签
对应的最新版本。

不同的标签可以有不同的版本,这就方便我们发表非稳定版本到 npm 上,与稳定版本分开。

默认是发布到 latest 标签下的。

例如 npm publish --tag dev 就可以发布一个版本到 dev 标签下。

4.3. 使用前缀

如果你使用过 AngularJS 或者 TypeScript,那么肯定知道有一些包的名字是这样的:

  • @types/node
  • @types/jquery
  • @angular/core

这里面的 @types/@angular/ 叫做包前缀(scope)。

作者起初以为使用包前缀也是收费的,后来仔细阅读了文档才发现公开的包可以免费使用
包前缀。

那我们怎么使用呢?很简单,首先在 package.json 里面把 name 字段加上一个前缀。

前缀必须是你 NPM 账户的用户名,比如你注册了一个用户名为 abc 的账户,则你只能使用
@abc/ 为你的包前缀。

举个例子,将你的包名设置为 @abc/test

如果你要初始化一个带包前缀的包,则可以使用下面的命令。

1
npm init --scope=abc # 当然你还可以加上个 `-y` 快速创建。

或者你想每次都使用 @abc/ 包前缀?加个设置即可:

1
2
# 这样每次初始化新的 package.json,都将自动应用 @abc/ 包前缀。
npm config set scope abc

现在,可以发布你的包到 npmjs.org 了。哦不,别忘了一点:

官方文档表示:所有带前缀的包,在发布的时候,默认都是发布为私有包。

这意味着你不能就这么发布,因为你(可能)不是付费用户,不能发布私有的包。那怎么办呢?别
担心,npm publish 命令还有一个参数 --access ,通过这个参数可以指定发布的是公共包
还是私有包。因此,只要用下面的命令就可以发布一个公共的,带包前缀的包了:

1
npm publish --access=public

(完)

文章目录
  1. 1. 0. 创建
  2. 2. 1. 准备
  3. 3. 2. 发布
    1. 3.1. 2.0. 修正下载源
    2. 3.2. 2.1. 创建并登录 npmjs.org 账户
  4. 4. 3. 真正的开始
    1. 4.1. 3.1. 合理的 package.json
    2. 4.2. 3.2. scripts 字段
    3. 4.3. 3.3. Git 设置
    4. 4.4. 3.4. NPM 包文件设置
    5. 4.5. 3.5. 配置 tsconfig.json
    6. 4.6. 3.6. 使用 tslint.json
  5. 5. 4. 维护
    1. 5.1. 4.1. 版本号维护
    2. 5.2. 4.2. 使用标签
    3. 5.3. 4.3. 使用前缀