发布 TypeScript 包到 NPM

最近将 yt-comment-date-format 从 1.0.3 更新到 2.0.1版本,支持Typescript。本文将记录更新流程。

首先去 NPM官网 注册账号,然后安装并配置 npm 和 node.js(推荐使用 nvm)。
初始化 NPM 项目 npm init -y,初始化 ts 配置文件 tsc –init
这两个操作将分别生成 package.jsontsconfig.json 文件。
然后我们逐步更新配置文件:

1. 添加 “declaration”: true 到你的 tsconfig.json

这行语句告诉 TypsScript 在编译的时候为你自动生成 d.ts 文件。需要注意的是,当你使用私有的类型时,但是这个类型也外部 API 的一部分,这个包的使用者就得不到该类型的类型推断,TS 编译器也会报警告,这时你只需要在该类型前添加 export 即可。

2. 添加 “types”: “index.d.ts” 到你的 package.json

当其他人导入你的包的时候,这句话就告诉了 TS 编译器到哪里去寻找类型定义文件。这里的 .d.ts 文件和 main 入口指向的是一个文件夹,所以通常情况下,你的 package.json 会包含下面两行:

1
2
"main": "dist/index.js",
"types": "dist/index.d.ts"

(上面默认你在 tsconfig.json 中配置的 outDir 指向的是 dist 目录)

3. 保证你的 dist 目录被添加到了 .gitignore

在我们的代码仓库,一般不需要包含编译后的代码,只需要包含源码即可。所以我们不对 dist 目录做版本管理。并且这也不影响我们发布 dist 目录到 npm。

4. 添加 npm scripts 构建命令

运行 tsc 即可编译所有的源码。这非常方便,通常情况下,我们可以添加一条命令到 package.json:

1
"build": "tsc"

5. 测试命令

为保证程序的质量,测试脚本是必不可少的:

1
"build": "tsc && node test.js"

6. 发布命令

修改代码和readme.md后,执行命令:

1
npm version patch

npm version 后面参数说明:

  • patch:小变动,比如修复bug等,版本号变动 v1.0.0->v1.0.1
  • minor:增加新功能,不影响现有功能,版本号变动 v1.0.0->v1.1.0
  • major:破坏模块对向后的兼容性,版本号变动 v1.0.0->v2.0.0

接下来就是要发布到 npm 了,在 package.json 添加以下命令:

1
"build": "tsc && npm publish --access public" # 共有包

当然前提得先注册、登录

1
2
3
npm adduser

npm login

如果想要在发布前调试本地包,可以使用 npm link 命令,在此项目根目录执行npm link, 然后在要调试的 demo 项目中执行 npm link ,然后在代码中直接引入使用即可。

最后,完成发布。(发布前需将镜像地址调回)

1
2
3
4
npm config set registry https://registry.npmjs.org
npm run build
npm login
npm publish

7. 撤销发布

1
2
3
npm unpublish package@1.0.0 删除某个版本的包
npm unpublish package --force 删除整个npm市场的包
npm deprecate [@] # 使用这个命令,安装时将提示不再维护

1、 删除某个版本 2、

不过撤包推荐用法: npm unpublish的推荐替代命令:npm deprecate [@] 使用这个命令,并不会在社区里撤销你已有的包,但会在任何人尝试安装这个包的时候得到警告 例如:npm deprecate z-tool ‘这个包我已经不再维护了哟~’

【注意】如果报权限方面的错,加上–force

8. 完整配置及代码

下面是完成配置后的 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
{
"author": {
"name": "yhorz.cn/csorz"
},
"bundleDependencies": false,
"dependencies": {
"dayjs": "^1.10.4"
},
"deprecated": false,
"description": "评论时间格式化",
"devDependencies": {
"typescript": "^4.2.4"
},
"license": "ISC",
"main": "dist/index.js",
"name": "yt-comment-date-format",
"scripts": {
"build": "tsc",
"release": "tsc && npm publish",
"test": "npm run build && node test.js"
},
"types": "dist/index.d.ts",
"version": "2.0.1"
}

下面是最终的 tsconfig.json:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"compilerOptions": {
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */'react-jsxdev'. */
"declaration": true, /* Generates corresponding '.d.ts' file. */
"outDir": "dist", /* Redirect output structure to the directory. */with --outDir. */'ES5' or 'ES3'. */
"strict": true, /* Enable all strict type-checking options. */
"esModuleInterop": true,
"skipLibCheck": true, /* Skip type checking of declaration files. */
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
},
"exclude": ["node_modules", "dist"]
}

入口文件 index.ts:

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
43
44
45
46
47
48
49
50
51
52
'use strict';

import dayjs from 'dayjs';

export function commentTimeFormat(time4server: number, time4comment: number) {
// 时间
const a = dayjs(time4server); // 服务器时间(当前)
const b = dayjs(time4comment); // 评论时间
const originDate = function (fm: string) {
return a.format(fm)
};
// 起点时间
const c = dayjs(originDate('YYYY-MM-DD')); // 起点时间(今天凌晨)
const d = dayjs(originDate('YYYY-01-01')); // 起点时间(今年1月1日凌晨)

// 时间差
const diff = a.diff(b, 'seconds'); // 评论已过秒数
const diffMinute = a.diff(b, 'minutes'); // 评论已过分钟数
const diffHour = a.diff(b, 'hours'); // 评论已过小时数
const diffTodayHour = a.diff(c, 'hours'); // 今天已过小时数
const diffCurrent = a.diff(d, 'seconds'); // 今年已过秒数

// 时间规则
const textConfig = ['刚刚', '分钟前', '小时前', '昨天 HH:mm', 'M月D日 HH:mm', 'YYYY年M月D日 HH:mm'];
let newTime = '';
if (diff > diffCurrent) {
// 往年
newTime = b.format(textConfig[5]);
} else {
// 今年
if (diffHour - diffTodayHour >= 24) {
// 前天及以前
newTime = b.format(textConfig[4]);
} else if (diffHour >= diffTodayHour) {
// 昨天
newTime = b.format(textConfig[3]);
} else {
// 今天
if (diffHour >= 1) {
// 1~23小时前
newTime = diffHour + textConfig[2];
} else if (diffMinute >= 1) {
// 1~59分钟前
newTime = diffMinute + textConfig[1];
} else {
// 1分钟内
newTime = textConfig[0];
}
}
}
return newTime
}

测试脚本 test.js:

1
2
3
4
5
6
7
8
9
10
11
12
const { commentTimeFormat } = require('./dist/index.js')
const now = 1560845869969
console.log(commentTimeFormat)
console.log(commentTimeFormat(now, now - 1000*59))
console.log(commentTimeFormat(now, now - 1000*60*59))
console.log(commentTimeFormat(now, now - 1000*60*60*23))
console.log(commentTimeFormat(now, now - 1000*60*60*24*1.9))
console.log(commentTimeFormat(now, now - 1000*60*60*24*17))
console.log(commentTimeFormat(now, now - 1000*60*60*24*31))
console.log(commentTimeFormat(now, now - 1000*60*60*24*100))
console.log(commentTimeFormat(now, now - 1000*60*60*24*500))
console.log(commentTimeFormat(now, now - 1000*60*60*24*900))

拓展

查看当前使用源地址:

1
npm config get registry

临时使用

1
npm --registry https://registry.npm.taobao.org install 包名

切换淘宝镜像

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

切回官方源

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

使用cnpm

1
npm install -g cnpm --registry=https://registry.npm.taobao.org

发布 TypeScript 包到 NPM
http://example.com/20210413-发布TypeScript包到NPM/
作者
csorz
发布于
2021年4月13日
许可协议