如何发布一个自己的node模块到npm

本文介绍如何创建一个自己的 node 模块,以及怎样发布到 npm ,与其他开发人员共享你的模块。

前言

作为一个前端开发人员,或者 nodejs 开发人员,目前我们使用最多的模块管理机制实属是 npm。我们可以使用很简单方式引用其他开发者发布到 npm 的模块。例如,当需要在你的项目中使用 vue。那么你可以:

1
$ npm install vue --save

安装 vue 模块到你的项目中,然后通过简单的导入命令使用她:

1
2
3
4
5
6
7
8
9
10
const Vue = require('vue')

// 或者使用 es Module 语法

import Vue from 'vue'

new Vue({
// ...
})

那么,我们自己怎样去创建一个自己模块,并且发布到 npmjs 呢?

准备

在开始之前,你需要有 3 样关键的工具,请确保你已经安装或者注册了。

  1. 编辑器,推荐使用 Visual Studio Code
  2. Node.js 环境
  3. npm 账户

创建一个模块

npm init

首先,我们要初始化一个 node 项目,也就是你的 node 包。随便在电脑的哪个位置创建一个新的文件夹,名字嘛,假定我们叫她 hello-npm-test。什么!你说她俗气?没办法!因为 苏大强 喜欢,我 苏明成 表示也没有办法。

OK!使用编辑器打开并进入到 hello-npm-test 文件夹,使用 npm init 初始化 package.json

1
$ npm init

这时你会看到一些提示:

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
42
elenh@elenh MINGW64 ~/Desktop/hello-npm-test
$ npm init
This 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 fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (hello-npm-test) hello-npm-test
version: (1.0.0)
description: a node test module which will be published to npm.
entry point: (index.js)
test command:
git repository:
keywords: npm node test
author: elenh
license: (ISC)
About to write to C:\Users\yisiw\Desktop\hello-npm-test\package.json:

{
"name": "hello-npm-test",
"version": "1.0.0",
"description": "a node test module which will be published to npm.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"npm",
"node",
"test"
],
"author": "elenh",
"license": "ISC"
}


Is this ok? (yes) y

具体的意思就是确定 package.json 文件中的一些必要字段信息。比如,包的名字 name ,包的语义化版本号 version ,包的描述信息 description,包的入口点 (entry point)main,测试脚本命令 (test command)script,git 仓库地址 (git repository),在 npm 中的搜索关键字 keywords ,包的作者名 author 以及该包的开源许可证类别 license

注:如果直接按回车的话,表示直接使用默认值设置该字段,但是作为一个即将要把包发布到 npm 的模块分享者来说,请仔细填写这些信息。因为这关系到该模块是否能正常使用(main 入口点),或者说别的开发者能够方便检索到你的模块(keywords, description)。很关键的一点是,你的 version 字段一定要遵循 npm 的语义化版本定义规则。以便使用此模块的开发者知道使用该模块的哪个版本。关于 语义化版本规则 请参考本博客的另一篇文章 npm使用说明

编写模块

现在,我们已经初始化好了 package.json 文件。是时候创建模块文件了。在 hello-npm-test 文件夹中新建一个名为 index.js 的文件。并在里面写入如下代码:

1
2
3
module.exports = function ( str ){
console.log( 'hello' + str )
}

如上,使用 CommonJs 模块语法默认导出了一个函数,代码质量及其酷炫。苏明玉 都表示很惊讶!

至于为什么使用名为 index.js 的文件呢?这边要说的话就需要展开 nodejs 的模块加载规则了,嗯,苏明哲让我别展开了,听大哥的话,所以请自行 Google

另一点需要说的是,在 package.json 文件中,我们定义了模块的入口点(entry point)main 字段,其默认值就是 index.js。她表示当使用模块导入语法使用该模块时,使用哪个文件作为入口点。当然,你可以修改她,比如:

1
2
3
{
"main": "src/index.js"
}

表示模块入口点为 src 文件夹下的 index.js 文件。

测试你的模块

到目前为止,你的模块已经可用了,那么怎么测试你的模块呢?此时,因为还没有发布到 npm ,所以不能使用如下方式直接安装。

1
$ npm install hello-npm-test

重新创建一个项目文件夹用来测试我们新写的模块,名为 my-project 。进入到该文件夹,初始化 node 项目。

1
npm init -y

此时,我们直接使用默认的 package.json 的设置即可,因为只是用来测试的。

同样,我们新建一个 index.js 文件,并准备在该文件中使用 hello-npm-test 模块。

两种方式来引用她:

  • 可以使用本地绝对路径引用的方式来使用她。

cd 进入到 my-project 文件夹中,并安装 hello-npm-test

1
$ npm install C:/Users/yisiw/Desktop/hello-npm-test

然后你可以看到 my-project 文件夹中的 package.json 文件中多出了 dependencies 字段如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"name": "my-project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"hello-npm-test": "file:../hello-npm-test"
}
}

index.js 中使用她。

1
2
3
4
5
6
// my-project/index.js

const log = require('hello-npm-test')

log('npm')

然后在终端执行:

1
2
$ node index.js
hellonpm

没错!成功的打印出了 hellonpm,鼓掌。

  • 你也可以使用 npm linkhello-npm-test 包关联到全局后通过 npm link hello-npm-test 来使用她。

首先进入到 hello-npm-test 文件中,打开命令行,输入如下命令:

1
npm link

这句命令的意思是将本模块地址关联到 nodejs 的全局环境中,以便可以在本机的任何项目中使用她。

1
$ E:\nodejs\node_modules\hello-npm-test -> C:\Users\yisiw\Desktop\hello-npm-test

执行完 npm link 后,会出现上方的提示信息,表示 hello-npm-test 模块的副本已经安装关联到 nodejs 的全局环境中了,你可以打开如上方的路径地址找到hello-npm-test 模块文件夹,就在 (E:\nodejs\node_modules\hello-npm-test)

为了同第一种方式区分开,我们首先把之前的 node_modules 文件夹、package-lock.jsonpackage.json 中的 dependencies 字段删除,然后进入到 my-project 文件夹中。输入如下命令:

1
2
3
4
5
6
npm link hello-npm-test

elenh@elenh MINGW64 ~/Desktop/my-project
$ npm link hello-npm-test
C:\Users\yisiw\Desktop\my-project\node_modules\hello-npm-test -> E:\nodejs\node_modules\hello-npm-test -> C:\Users\yisiw\Desktop\hello-npm-test

执行完 npm link hello-npm-test 命令后,你会发现,my-project 文件夹中的 node_mnodules 又出现了,并且里面存在 hello-npm-test 包。那么我们再次执行:

1
2
$ node index.js
hellonpm

没错,同样是有用的。

将模块管理到 Github

接下来,我们应该将我们的包使用版本控制工具管理起来,方便之后的维护及更新。没错!是 Github。理所当然!

1
2
3
4
5
6
7

$ git init
$ git add .
$ git commit -m 'Initial commit'
$ git remote add origin https://github.com/yisibell/hello-npm-test
$ git push -u origin master

然后在 package.json 文件中加入 homepage 字段,并写上你的仓库地址或者项目文档地址。这样,当用户在 npm 中查看你的包信息时,就可以看到她。帮助用户熟悉并使用。

1
2
3
{
"homepage": "https://github.com/yisibell/hello-npm-test"
}

添加 README.md

在开发完你的包功能后,你应该创建一个 README.md 文件来描述你的包。

  • 这个包怎么安装
  • 这个包是用来干什么的
  • 这个包解决了什么问题
  • 这个包有哪些配置项及APIS

独立说明文档

如果,你的包提供的功能特别多,比如像,一些 UI 组件库,她会提供很多组件,指令,api 服务等。

那么,一个简单的 README.md 就不是很合适了,目前,推荐的方式是,使用 vuepress, hexo 等这类静态站点部署工具,来构建文档。

然后,部署在 GitHub Pages 或者 Gitee Pages 上。

这里推荐一个快速构建文档的框架: aidol 。基于 vuepress

具体细节,可参照其说明文档,进行构建部署。

添加.npmignore

在开发你的包的过程中,你可能会新建一些依赖文件,测试文件等,比如:

1
2
3
4
package-lock.json
node_modules/
.gitignore
test/

打包构建配置、以及 .npmignore 自身。这些都是不需要发布到 npm 上的。

判别的基本原则就是,与该包不相关且其他人引入时,不需要加载的,我们都应该进行忽略。

cd 进入到 hello-npm-test ,打开你的终端命令行敲入 touch .npmignore 在项目包的根目录下新建 .npmignore 文件。

1
touch .npmignore

然后在该文件中写入你要忽略的文件、文件夹配置。

1
2
3
4
node_modules/
.gitignore
test/
package-lock.json

注意:可别把 package.json 忽略掉了。这是必须上传的关键文件,该包的信息都被保存在该文件中,使用者使用导入语法导入该模块时,也是通过 package.json 文件中的 main 字段来查找入口文件。

发布到 npm

最后一步就是发布你的模块到 npm。进入到 hello-npm-test ,打开命令行。敲入如下命令:

1
2
3
4
5
6
# 添加用户
$ npm adduser

# or
# 直接登录
$ npm login

结果:

1
2
3
4
5
6
elenh@elenh MINGW64 ~/Desktop/hello-npm-test (master)
$ npm adduser
Username: elenh
Password:
Email: (this IS public) yisiwings@163.com
Logged in as elenh on https://registry.npmjs.org/.

按提示输入 用户名(Username)、密码(Password)以及邮箱(Email)后,便会提示你已经作为谁谁谁登陆到了 npm

1
Logged in as elenh on https://registry.npmjs.org/.

你可以使用 npm version 查看该模块当前所处的版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ npm version
{ 'hello-npm-test': '1.0.0',
npm: '5.6.0',
ares: '1.10.1-DEV',
cldr: '32.0',
http_parser: '2.8.0',
icu: '60.1',
modules: '57',
napi: '3',
nghttp2: '1.29.0',
node: '8.11.2',
openssl: '1.0.2o',
tz: '2017c',
unicode: '10.0',
uv: '1.19.1',
v8: '6.2.414.54',
zlib: '1.2.11' }

当前版本为 1.0.0

紧接着就是将包发布。

1
2
3
4
5
# 私有包发布方式
$ npm publish

# 开源包发布方式
$ npm publish --access=public

在发布的过程中,你可能会遇到一些错误,比如 npm 中已经有存在你当前的这个包名了。那么修改你的包名再发布。

使用

现在,你可以使用诸如:$ npm install hello-npm-test --save,这样的方式来安装你自己的包了,并且在其他项目中使用她。

1
2
3
4

const log = require('hello-npm-test')
log(',明玉')

打印结果:

1
2
3
4

$ node index.js
hello,明玉

维护和升级

你的包在不断使用的过程中,使用者们或你自己会发现,她存在某些 BUGS ,或者需要优化,再或者你需要添加新的功能 APIS

假定,你已经对包升级完毕,那么怎样更新 npm 上的包数据呢?这同样很简单,你只需要按照 语义化版本规则 更新你的版本号后,再修改下 README.md 说明文档,指出你的哪些改动,以及新的 API 用法。

你就可以在该包根目录下打开命令行再次键入:

1
$ npm publish --access=public

你的包就会在 npmjs 被更新为一个新的版本。使用者们,不定期的执行 npm outdated 就会看到你的包的更新情况,并更新他们本地的包文件。

版本号更新方式

通常,当你的爱包中的代码被你优化修改了,你需要先升级你的包版本号,然后再 npm publish。你有以下两种更新版本号的方式。

  1. 手动修改 package.json 中的 version 字段,注意遵循 语义化版本规则。然后再 npm publish
  2. 使用 npm version <update_type> 命令。

其中 update_type 参数有 3 个常用可选值:patch , minormajor

  • patch 表示补丁级别的版本更新,即递增第三位版本号
  • minor 表示小版本级别的版本更新,即递增第二位版本号
  • major 表示大版本级别的版本更新,即递增第一位版本号

<update_type> 的其他值,不在此处列出,| premajor | preminor | prepatch | prerelease [--preid=<prerelease-id>] | from-git

例:当前 hello-npm-test 的版本号为 1.0.1,我们现在对小版本进行更新。

1
2
$ npm version minor
v1.1.0

如上打印结果,版本号已经升级到了第二位上,注意,因为是递增制,所以第三位版本号恢复从 0 开始。

然后你就可以将新的版本发布到 npm 了。

1
$ npm publish --access=public

注意:在使用 npm version <update_type> 更新版本号之前,你需要先将你的代码提交到 github 否则会调用命令失败!