其实,我们每天都在使用 npm
或 yarn
在 https://www.npmjs.com 平台下载一些第三方的包,它们都属于开源的,任何人都可以免费下载并使用。
假设公司或者团队里面,想把一些可复用的模块抽离并形成 NPM 包,因涉及公司业务或其他原因,不能发布到 NPM 平台上。这时候我们可以在公司内部建立一个类似 https://www.npmjs.com 的私有的 NPM 平台,怎么做呢?
下面,我们从零到一搭建个人的 NPM 私有服务器。
一、选择
选择 Verdaccio 作为我们私有 NPM 仓库的平台,主要原因是免费、零配置,开箱即用。
当然,公司应该选择其他更加可靠、稳定付费平台了,本文适合个人玩耍~
二、NPM 平台搭建
安装、启动都非常简单~
# install
$ npm i -g verdaccio
# run
$ verdaccio
Verdaccio 跑起来之后,可以看到仓库地址就是:http://localhost:4873/
。
这是基于默认配置,暂时不作修改,配置文件在 /Users/frankie/.config/verdaccio/config.yaml
。
frankie@MacBook-Pro Verdaccio % 🐶 verdaccio
warn --- config file - /Users/frankie/.config/verdaccio/config.yaml
warn --- Plugin successfully loaded: verdaccio-htpasswd
warn --- Plugin successfully loaded: verdaccio-audit
warn --- http address - http://localhost:4873/ - verdaccio/5.1.1
http --- 127.0.0.1 requested 'GET /'
http --- 304, user: null(127.0.0.1), req: 'GET /', bytes: 0/0
http --- 127.0.0.1 requested 'GET /-/verdaccio/packages'
http --- 304, user: null(127.0.0.1), req: 'GET /-/verdaccio/packages', bytes: 0/0
目前没有发包上来,就长这样...
我们修改以下 npm
或 yarn
的镜像源 http://localhost:4873/
。
# 添加私有源(我使用了 nrm 来管理 npm 源)
$ nrm add frankie-loc http://localhost:4873/
# 切换源
$ nrm use frankie-loc
# or
# npm set registry http://localhost:4873/
# 注册用户,对应你 NPM 账号密码(若没有,用邮箱注册一个即可)
$ npm adduser
# 查看当前用户是否是注册用户
$ npm who am i
关于 nrm 安装使用,看这里。
三、发包
3.1 创建 NPM 项目
我们来创建一个最简单的 NPM 包项目,目录如下:
privative-npm
├── .gitignore // 相应目录,发布时会忽略上传
├── .npmignore // 同理,会忽略上传
├── index.js // 作为入口
├── package.json // 包描述文件
└── README.md // 项目说明
一个 NPM 包,其中 name
和 version
是必需的,其他都可以省略,而且 name 不能与平台上已有包重名。
// package.json
{
"name": "privative-npm", // 必需,不能有大写字母、空格、下划线
"version": "1.0.0", // 必需,请严格遵循语义化
"description": "Test only, not published to NPM.",
"author": "Frankie <1426203851@qq.com>",
"license": "MIT",
"type": "module",
"main": "./index.js"
}
由于演示而已,我们就只导出一个方法吧。注意,若在 node 下运行此包,我们使用了 ESM,因此需要在 package.json
设置 "type": "module"
。
// index.js
export default function log(str) {
console.log(str)
}
3.2 发布 NPM 包
在发包之前,你需要去 NPM 平台官网注册一个账号。很简单省略...
完了之后,登录你的 NPM 账号:
# add
$ npm set registry http://localhost:4873/
# switch registry
$ npm config set registry http://localhost:4873/
# login npm account
$ npm adduser
# 登录过用 login,第一次则用 adduser,它包括了登录操作。
$ npm login
登录成功,长这样:
frankie@MacBook-Pro privative-npm % 🐶 npm login
Username: xxx
Password:
Email: (this IS public) 1426203851@qq.com
Logged in as xxx on http://localhost:4873/.
在跟目录下,执行命令 npm publish
即可。或可在 package.json
脚本命令中定义。(后者更合适)
frankie@MacBook-Pro privative-npm % 🐶 npm publish
npm notice
npm notice 📦 privative-npm@1.0.0
npm notice === Tarball Contents ===
npm notice 54B index.js
npm notice 212B package.json
npm notice 36B README.md
npm notice === Tarball Details ===
npm notice name: privative-npm
npm notice version: 1.0.0
npm notice package size: 416 B
npm notice unpacked size: 302 B
npm notice shasum: 887836aa4a154902faf31b13e60b8adcdd07b924
npm notice integrity: sha512-fyzitNqmif188[...]hFY+zmcIW6qTg==
npm notice total files: 3
npm notice
+ privative-npm@1.0.0
看到已经上传成功了,刷新页面就能看到:
3.3 更新包
如果我们要更新包,其中版本号 version
一定要修改,否则会更新失败,如下:
frankie@MacBook-Pro privative-npm % 🐶 npm publish
...
npm ERR! code EPUBLISHCONFLICT
npm ERR! publish fail Cannot publish over existing version.
npm ERR! publish fail Update the 'version' field in package.json and try again.
npm ERR! publish fail
npm ERR! publish fail To automatically increment version numbers, see:
npm ERR! publish fail npm help version
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/frankie/.npm/_logs/2021-07-14T06_16_31_553Z-debug.log
这里我就只改个版本号吧,更新包的命令仍然是 npm publish
,上传成功后,刷新页面可以看到新版本了。
另外,假设你开发了一个 NPM 包,然后要发布到 NPM 开源供其他开发者使用,一定要按照语义化版本规律进行更新。如果像本文在本地或个人服务器搭建着玩,就爱咋咋地!
3.4 撤销包
需要注意的是,在 NPM 平台撤销包,是有非常严格限制的,不是随意就能撤销已发布到平台的包的,详情可看:NPM Unpublish Policy。
# 撤销包的某个版本
$ npm unpublish [<@scope>/]<pkg>@<version>
# 撤销包
$ npm unpublish [<@scope>/]<pkg>
如果你的目的是鼓励用户升级,或者您不想再维护软件包,请考虑改用 deprecate
命令。
$ npm deprecate <pkg>[@<version>] <message>
我们在安装一些依赖包的时候,不是经常看得到类似的东西吗,就是 deprecate
搞的鬼~
npm WARN deprecated core-js@1.2.7: core-js@<3.3 is no longer maintained and not recommended for usage due to the number of issues.
四、使用包
我们将 NPM 发布到私有或公开的 NPM 平台后,都可以通过 npm
、yarn
等包管理工具去安装到我们的项目中。
由于我们上面示例,是将 privative-npm
包发布到我们私有的 NPM 服务器下,因此需要将 npm 镜像源切换至 http://localhost:4873/
即可:
# use npm
$ npm config set registry http://localhost:4873/
# use yarn
$ yarn config set registry http://localhost:4873/
随便创建一个项目,并安装 privative-npm
依赖包,在 node 环境运行一下 index.js
可以看到打印出 OK!
,那说明成功了!
五、其他
假设我们在使用 http://localhost:4873/
镜像源,去安装 react
、vue
等包,它是怎么处理的呢?
首先,我们了解一下正常使用 NPM 安装、共享、发包的流程:
当我们使用 npm
或 yarn
去安装一个模块(包)时,先检查 node_modules
目录是否已经缓存了该模块,如果没有便会向 NPM 平台查询。
NPM 提供了一个模块信息查询服务,通过访问:
registry.npmjs.org/packaename/version
就可以查到某个发布在 NPM 平台上模块的具体信息,以及下载地址。然后下载并解压到本地完成安装。
如果我们启用了私有 NPM 服务器,流程又有什么变化呢?
当我们启动 Verdaccio 时,可以看到配置文件是在用户根目录下的:/Users/frankie/.config/verdaccio/config.yaml
。
#
# 配置文件(这里我删除了一些默认注解)
# 更多请看: https://github.com/verdaccio/verdaccio/blob/master/packages/config/src/conf/default.yaml
#
# 上传的所有包存放目录
storage: ./storage
# 插件目录
plugins: ./plugins
# web 服务,即我们可以通过 web 查看我们上传的包。
web:
title: Verdaccio
# 一些关于 web 页面的配置项,我删掉了
# 验证信息
auth:
htpasswd:
# 用户信息存储目录
file: ./htpasswd
# 公有仓库配置
uplinks:
npmjs:
# 默认
# url: https://registry.npmjs.org/
# 我们可以改成淘宝镜像源
url: https://registry.npm.taobao.org/
packages:
'@*/*':
# scoped packages
access: $all
publish: $authenticated
unpublish: $authenticated
# 代理。当我们安装一些私有服务器上没有的包时,它就会往这里找,即上面的 uplinks 配置
proxy: npmjs
'**':
# 三种角色:所有人、匿名用户、认证(登录)用户
# "$all", "$anonymous", "$authenticated"
# 可访问包角色
access: $all
# 可发包、撤包角色
publish: $authenticated
unpublish: $authenticated
# if package is not available locally, proxy requests to 'npmjs' registry
proxy: npmjs
# 服务连接活跃时间
server:
keepAliveTimeout: 60
middlewares:
audit:
enabled: true