怎么发布一个 npm 包到 npm 官方 registry

2,500 阅读7分钟

简单说下 npm 是什么

  • npm 是一个 node 模块管理工具,也是全球最大的共享源。 npm 工具与 nodejs 配套发布,便利开发人员共享代码,npm 也提供了私有化发布的付费功能。npm 主要包括 npm 官方网站、CLI(控制台命令行工具)、和 registry(包/软件仓库)。
  • 我们可以通过 npm 官网进行感兴趣的包的搜索、npm 用户信息的管理、文档查阅等。
  • 我们通过 CLI 来进行 npm 目录的初始化(npm init)、 包的安装(npm install)、发布(npm publish)、更新(npm update)。
  • 是一个巨大的软件池,可以理解为一个很大的软件仓库。里面包含了全球开发者的智慧结晶,当我们需要某些轮子的时候,可以直接通过 CLI 从 npm registry 中获取到。基本上热门的 js 开源代码都能在 npm 中找到对应的发布包。

为什么需要发布自己的 npm 包

  • 我们需要在项目之前共享代码。比如我们的项目分为通用工具库、基础组件库、业务通用库等。这些库可以进行独立的开发、发版、维护。因为足够通用,我们可以通过将这些库发布为 npm 包来解决代码共享的问题。否则我们很可能需要手动拷贝这些代码。
  • 我们可能愿意将自己使用的一些好的代码共享(开源)给广大网友扩大自身技术影响力
  • 我们希望以统一的包管理、依赖管理(依赖获取)方式来组织自己的代码,统一项目构建流程。

如何发布一个 npm 包到官方

创建 npm 账户

  1. 打开 www.npmjs.com , 选择 sign up 进入账户注册页面
  2. 根据提示填写注册信息,点击注册后,填写的邮箱会收到一个验证码,输入验证码后即可完成注册。 注册.png
  3. 完成注册后就可以看到 npm 个人主页了,到这里注册账户已经完成了。

image.png

本地创建 npm 包

  1. 新建一个文件夹 my-test001-datetime,用于开发一个 npm 包
mkdir my-test001-datetime
  1. 进入命令行运行 npm init
cd my-test001-datetime 
npm init
  1. 根据提示填写 npm 包信息,括号里为默认值。不填写默认会使用默认值。
package name: (my-test001-datetime)  //定义包名,默认使用和文件夹一样的名字
version: (1.0.0) // 包的版本号
description: //包的描述信息
entry point: (index.js) //包的入口,在引入包的时候的 import 或 require 的指向
test command:  //包的测试命令,运行 npm run test 的执行体
git repository: //git 链接,如果该包是 git 开源的话可以填写这个
keywords: // 搜索关键字,帮助在 npm 网页搜索
author: //作者
license: (ISC)//开源协议 

执行完成后会产生一个 package.json 文件,内容即为刚刚填写的内容。到这里,npm 包的基本初始化已经完成了

{
  "name": "my-test001-datetime",
  "version": "1.0.0",
  "description": "just a test",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

发布 npm 包

  1. 以上我们创建的 pakage.json 指明了入口函数为 index.js,现在在文件夹下创建一个 index.js
touch index.js

编辑 index.js 写入一个简单的 cjs 导出函数,当然我们也可以编写 es6 的导出(export xxx)。

function hello(name) {
    return 'hello ' + name + ', now is ' + Date();
}
module.exports = {
    hello
}
  1. 在控制台执行 npm login,username 使用刚刚创建的账号码,email 使用注册使用的 email。 OTP 验证码会通过该邮箱发送,最后填写验证码即完成 npm 登陆。
npm login
Username: xxxx
Password: xxxx
Email: (this IS public) 
npm notice Please check your email for a one-time password (OTP)
Enter one-time password from your authenticator app: 
  1. 在控制台通过 npm profile get 查看当前 npm 用户信息
| name            │ xxx                │
├─────────────────┼─────────────────────────────┤
│ email           │ ccccxc@xxx.xxx(verified)    │
├─────────────────┼─────────────────────────────┤
│ two-factor auth │ disabled                    │
├─────────────────┼─────────────────────────────┤
│ fullname        │                             │
├─────────────────┼─────────────────────────────┤
│ homepage        │                             │
├─────────────────┼─────────────────────────────┤
│ freenode        │                             │
├─────────────────┼─────────────────────────────┤
│ twitter         │                             │
├─────────────────┼─────────────────────────────┤
│ github          │                             │
├─────────────────┼─────────────────────────────┤
│ created         │ 2022-02-10T03:19:39.873Z    │
├─────────────────┼─────────────────────────────┤
│ updated         │ 2022-02-10T03:19:39.869Z 
  1. 执行 npm publish,即完成发布
npm publish 
npm notice 
npm notice 📦  my-test001-datetime@1.0.0
npm notice === Tarball Contents === 
npm notice 215B package.json
npm notice 90B  index.js    
npm notice === Tarball Details === 
npm notice name:          my-test001-datetime                     
npm notice version:       1.0.0                                   
npm notice package size:  338 B                                   
npm notice unpacked size: 305 B                                   
npm notice shasum:        8db3b2be369857a0090c868ced510153b5bbd4c6
npm notice integrity:     sha512-qbxSVkoYX01fZ[...]1KnRL2UT1HwDg==
npm notice total files:   2                                       
npm notice 
+ my-test001-datetime@1.0.0

验证发布的包

  1. 打开 npm 官网个人主页下已经可以看到新发布的包 image.png
  2. 创建一个新项目来引用一下试试,新建一个文件夹 test-mypackage,执行 npm init,填写完成 npm 项目基本信息,执行 npm install my-test001-datetime
mkdir test-mypackage
cd test-mypackage
npm init
npm install my-test001-datetime

3.创建 index.js 文件, 在 index.js中编写如下代码。

const hello = require('my-test001-datetime').hello;
console.log(hello('Kitty'));
  1. 此时我们已经完成了代码编写,直接执行 node injdex.js 我们将看到 hello 方法调用成功。
node index.js
hello Kitty, now is Thu Feb 10 2022 13:53:46 GMT+0800 (GMT+08:00)

5.在 test-mypackage 目录下的 node_moudles 文件夹(该项目下局部安装的所有 npm 包都在这个目录下)下也能找到我们安装的自己刚发布的包。

创建域隔离包(scope package),@xxx/xxx,型如 @babel/preset-env

我们在开发项目中常常见到这样的引用,比如 @babel/xxx,@react/xxx,@types/xxx

import xx from @xxxx/xxx

这样的包类似于用命名空间区分同名类,在 npm 中称为 scope。这样的包可以帮助我们创建一个语义化的报名但不用担心因为重名无法发布。比如我们想发布一个 datetime 的包,但是这个包名已经被占用了,我们可以选择创建一个属于自己的 datetime 包。

  1. 首先在 npm 网页上创建一个组织,点击头像下的 【+ Add Organization】

  2. 创建组织后可以发私有包(需要付费),我们选择免费的就行。填写组织名 iamme007,以后就可以在创建类似于 @iamme007/datetime 的包了。 image.png

  3. 创建一个 scope package。 这一步类似于上面的创建操作。唯一不同是 npm init 时需要通过--scope 指明 scope

 mkdir my-test002-datetime
 cd my-test002-datetime
 npm init --scope=@iamme007
 
 
 package name: (@iamme007/my-test002-datetime) datetime
 version: (1.0.0) 
 description: 
 entry point: (index.js) 
 test command: 
 git repository: 
 keywords: 
 author: 
 license: (ISC)

创建完成后 package.json 文件内容如下。可以注意到 name 已经变成了 @iamme007/datetime

{
  "name": "@iamme007/datetime",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

  1. 同样的创建 index.js 文件,写入上文相同的代码。接下来就是发布了。
  2. 与常规发布不同,这里我们发布需要注意,由于我们使用的是免费的组织管理,所以只能发公共包。即我们运行 npm publish 时要加上 --access public(scoped package 默认为私有发布)。 否则会提示付费。
npm publish --access public
  1. 发布完成后到 npm 网站也可以看到刚发布的 @iamme007/datetime 了。 安装验证就直接运行 npm install @iamme007/datetime 就可以了。

image.png

私有 npm 包

使用 npm 付费服务

npm 提供了付费服务,支持私有包的创建。个人用户一个月 7 刀。团队组织的一个成员一个月 7 刀。都支持无限创建私有包。

搭建自己的 npm 服务

实际开发中,我们需要一些内部共享的 npm 包,所以在企业内部搭建一个私有 npm 源也很重要。

  1. npm 支持安装 git 仓库,可以直接使用私有 git 仓库支持 npm 包.如
npm install git+<https://xxx.xx/mypkg.git>
  1. 使用 jfrog artifactory 作为 npm registry
  2. verdaccio (开源的轻量的私有的npm proxy registry)、
  3. cnpm + cnpmjs.org (基于 KOA 的私有 npm 源方案)
  4. 其他 Sinopia(不再维护),npm-register(需要亚马逊云支持)