从0到1发布一个npm包

1,219 阅读5分钟

本文作者:路世翠

1. 发布一个npm包

1.1 初始化

采用npm init命令 or 脚手架初始化npm 包

npm init
------------------
package name: (npm-demo) 
version: (1.0.0) 
description: 一个plus方法
entry point: (index.js) app.js
test command: npm run test
git repository: https://git.xxx.com/base-fe/xxx/npm-demo
keywords: npm
author: olina
license: (ISC)

1.2 包开发

包括包的功能开发及调试过程

1.2.1 功能开发

完成包的功能实现

1.2.2 调试

在开发过程中,如何快速验证、调试修改内容

(1)不断发布beta版本 ✖️
  • 优:升级包版本,多人可用
  • 缺:重复繁琐
(2)根据相对路径install ✖️
cd ~/Desktop/demo/npm-demo
npm install /Users/olinalu/ke/ke-components/packages/ke-form
  • 优:操作简单
  • 缺:调试过程中的改动,需反复install
(3)使用软链 ✔️
cd ~/Desktop/demo/npm-demo/node_modules   # cd至项目目录的node_modules下
ln -s /Users/olinalu/ke/ke-components/packages/ke-form @ke/ke-form    # 通过ln -s <package path> <package name>链接包

删除软链

cd ~/Desktop/demo/npm-demo/node_modules
rm -rf @ke/ke-form
  • 优:两边的修改同步
  • 缺:不同操作系统语法不同
(4)npm link ✔️
cd packages/ke-form         # cd至包目录下
npm link                    # 创建与全局node_modules的链接
cd ~/Desktop/demo/npm-demo  # cd至项目目录下
npm link @ke/ke-form        # 通过npm link <package name>将包链接到当前目录下

建立联系如下

/Users/olinalu/Desktop/demo/npm-demo/node_modules/@ke/ke-form -> /usr/local/lib/node_modules/@ke/ke-form -> /Users/olinalu/ke/ke-components/packages/ke-form

全局node_modules下面写入该package

简化操作

cd ~/Desktop/demo/npm-demo  # cd至包目录下
npm link /Users/olinalu/ke/ke-components/packages/ke-form  # 通过npm link <package path>将包链接到当前目录下

这样,packages/ke-form中的所有修改都会同步到~/Desktop/demo/npm-demo/node_modules/@ke/ke-form下

tips

  • 上述方式不会将npm包写进package.json中
  • webpack4中resolve.symlinks属性默认为true,在npm link时模块解析失败,需要将该属性手动修改为false

Uncaught (in promise) Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object

解除 link

在项目下执行命令:npm unlink @ke/ke-form

1.3 发布

包的发布过程通过以下流程来完成

1.3.1 发布内容管理

  • 白名单:读取package.json中的files属性(默认包含package.json, README.md, LICENSE文件)
"files": ["src", "app.js"]
  • 黑名单:读取.gitignore 或 .npmignore,忽略相应文件(.npmignore > .gitignore),.npmignore不会覆盖 files 中的根目录字段,但可覆盖子目录
  • 查看当前包所要发布的文件:npx npm-packlist

1.3.2 采用npm version控制版本

npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease [--preid=<prerelease-id>] | from-git]

X.Y.Z-beta

更新版本指令含义
X.Y.Znpm version major破坏性改动
X.Y.Znpm version minor兼容性改动
X.Y.Znpm version patch更新补丁
X.Y.Z-betanpm version prerelease发布测试包

1.3.3 包发布

(1)源管理(once)

获取当前源:npm get registry
修改源:npm config set registry=http://registry.npmjs.org

(2)账户、权限申请(once)

npm公共镜像:注册账户、邮箱激活、本地npm login、执行npm whoami成功即可

(3)publish(every time)
  • npm publish发布最新的正式包
  • npm publish --tag <tag>发布测试包
(4)删除包(72h时间限制)
  • 删除某一版本的包:npm unpublish [<@scope>]<pkg>@<version>
  • 删除整个包:npm unpublish [<@scope>]<pkg> --force

2. 安装

2.1 包版本

2.1.1 npm ls

以树结构打印已安装的所有包、版本号及其依赖,该依赖关系为包之间依赖的逻辑关系,而非node_modules中的目录结构

2.1.2 npm outdated

查看版本是否最新

current:当前安装版本
wanted:满足package.json中版本号语义的最高版本
latest:当前包已发布的最高正式版本
红色:当前版本语义下有新版本可更新
黄色:已是当前语义版本下最新版本

2.1.3 npm update [-g] [<pkg>...]

  • 更新全局/项目中的依赖至当前语义下最新版本
  • 不指定包名时,更新当前环境下所有包
版本安装指令含义
X.Y.Znpm install packageName -D/S --save-exact精确版本号
^X.Y.Znpm install packageName安装 >=X.Y.X <(X+1).0.0版本
~X.Y.Z手动修改package.json安装 >=X.Y.X < X.(Y+1).0版本

2.1.4 npm install

  • 不带参数:安装package.json中的所有包
  • npm install <folder>:将相应目录下的包以符号链接的形式安装在当前项目中
  • npm install [<@scope>]<name>:安装特定包

2.2 包的扁平化

2.2.1 npm install

包结构:A{B,C}, B{C}, C{D}

A
+-- B
|   `-- C
|       `-- D    No
`-- C
    `-- D 

A
+-- B
+-- C      Yes
+-- D
包结构:A{B,C}, B{C,D@1}, C{D@2}

A
+-- B
+-- C
   `-- D@2
+-- D@1

安装顺序不同时,生成的树结构可能不同

2.2.2 npm dedupe

查找本地包的树结构,通过简化树结构来使得包之间更好的共享依赖。当包之间出现依赖冗余时,可通过npm dedupe进行重新计算,效果如下:

before

a
+-- b <-- depends on c@1.0.x
|   `-- c@1.0.3
`-- d <-- depends on c@~1.0.9
    `-- c@1.0.10

after

a
+-- b
+-- d
`-- c@1.0.10

More...

package.json各字段含义

name

标识包名称,发布包中必须

version

标识包版本,发布包中必须

main

项目入口文件

scripts

根据不同的生命周期钩子执行对应命令

files(.npmignore)

发布白名单:默认包含package.json, README.md, LICENSE文件

dependencies

项目上线or发布npm包时所需要

devDependencies

项目开发时需要(babel、webpack等)

peerDependencies

提示宿主环境去安装npm包在peerDependencies中所指定依赖的包;npm 3.x ~ 6.x,抛出warning提示安装,npm 7.x中,默认安装依赖包(为减少npm包与宿主环境依赖版本冲突问题,尽量不锁定此处版本)

Tips

在业务项目中dependencies和devDependencies没有本质区别,只是单纯的规范作用,在执行npm install时两个依赖下的模块都会被下载;而在发布npm包的时候,包中的dependencies依赖项在安装该包的时候会被一起下载,devDependencies依赖项则不会。

参考文章