@cdfrd/publish-notification-plugin 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +146 -5
- package/dist/index.cjs +62 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +62 -16
- package/dist/index.js.map +1 -1
- package/dist/{types-DaCJHaWX.d.cts → types-CtjSwxB7.d.cts} +8 -10
- package/dist/{types-DaCJHaWX.d.ts → types-CtjSwxB7.d.ts} +8 -10
- package/dist/version.d.cts +2 -2
- package/dist/version.d.ts +2 -2
- package/dist/vite.cjs +20 -6
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.d.cts +2 -2
- package/dist/vite.d.ts +2 -2
- package/dist/vite.js +20 -6
- package/dist/vite.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -29,20 +29,31 @@ createUpdateNotice()
|
|
|
29
29
|
|
|
30
30
|
## 微前端(qiankun)
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
每个子应用各自接入 `vitePluginVersion()` + `createUpdateNotice`;Host 同步 `setActiveApp`。
|
|
33
33
|
|
|
34
34
|
```ts
|
|
35
|
-
//
|
|
35
|
+
// vite.config.ts
|
|
36
|
+
import { defineConfig } from 'vite'
|
|
37
|
+
import { vitePluginVersion } from '@cdfrd/publish-notification-plugin/vite'
|
|
38
|
+
|
|
39
|
+
export default defineConfig({
|
|
40
|
+
plugins: [vitePluginVersion()],
|
|
41
|
+
})
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
// 主应用: host/main.ts
|
|
36
46
|
import { createUpdateNotice, getUpdateNotice } from '@cdfrd/publish-notification-plugin'
|
|
37
47
|
|
|
38
48
|
createUpdateNotice({
|
|
39
49
|
microApp: { enabled: true, appId: 'host' },
|
|
40
|
-
//
|
|
50
|
+
// 主应用纯壳(可选):disableNotification: true,
|
|
41
51
|
})
|
|
42
52
|
|
|
43
53
|
registerMicroApps(apps, {
|
|
44
54
|
beforeMount: [
|
|
45
55
|
(app) => {
|
|
56
|
+
// 激活子应用(插件只检查激活子应用是否有版本,不检查其他子应用)
|
|
46
57
|
getUpdateNotice()?.setActiveApp(app.name)
|
|
47
58
|
return Promise.resolve()
|
|
48
59
|
},
|
|
@@ -51,21 +62,151 @@ registerMicroApps(apps, {
|
|
|
51
62
|
```
|
|
52
63
|
|
|
53
64
|
```ts
|
|
54
|
-
// order/main.ts
|
|
65
|
+
// 子应用:order/main.ts
|
|
55
66
|
createUpdateNotice({
|
|
56
67
|
microApp: { enabled: true, appId: 'order-center' },
|
|
57
68
|
})
|
|
58
69
|
```
|
|
59
70
|
|
|
71
|
+
|
|
72
|
+
|
|
60
73
|
## 事后切换语言 / 主题
|
|
61
74
|
|
|
62
75
|
```ts
|
|
63
76
|
import { getUpdateNotice } from '@cdfrd/publish-notification-plugin'
|
|
64
77
|
|
|
65
78
|
getUpdateNotice()?.setLocale('en_US')
|
|
79
|
+
// 如果是 Antd UI 4.x + 5.x +6.x ,可以不用写下面这行
|
|
80
|
+
// Antd主题会自动适配,不需要额外配置
|
|
66
81
|
getUpdateNotice()?.setTheme('dark')
|
|
67
82
|
```
|
|
68
83
|
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
## `UpdateNoticeOptions`
|
|
87
|
+
|
|
88
|
+
`createUpdateNotice(options?)` 的运行时配置。
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
| 字段 | 类型 | 默认 | 说明 |
|
|
92
|
+
| --------------------- | -------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
93
|
+
| `versionBase` | `string` | 自动推导 | `version.json` URL 前缀,最终请求 `{versionBase}update-notice/version.json`。优先级:显式 `versionBase` → Vite `import.meta.env.BASE_URL` → `''`。非根路径 / CDN 部署时建议显式配置 |
|
|
94
|
+
| `check` | `CheckConfig` | 见下表 | 版本检查触发策略 |
|
|
95
|
+
| `microApp` | `MicroAppConfig` | — | 微前端场景配置 |
|
|
96
|
+
| `themeAdapter` | `ThemeAdapterConfig` | `{ type: 'antd' }` | 默认 UI 主题适配 |
|
|
97
|
+
| `placement` | `'topLeft' | 'topRight' | 'bottomLeft' |
|
|
98
|
+
| `forcedUpdate` | `boolean` | `false` | `true` 时强制更新:无「稍后」/关闭,展示倒计时与「立即刷新」,倒计时结束自动刷新;页面无遮罩仍可操作 |
|
|
99
|
+
| `locale` | `LocaleConfig` | — | 按语言覆盖内置通知文案;整站当前语言由 `setLocale` 控制,内置默认 `zh_CN` |
|
|
100
|
+
| `disableNotification` | `boolean` | `false` | `true` 时完全关闭该应用的检查 / 默认 UI / `web_update_notice`。纯壳 Host 常用。与 `hiddenDefaultNotice` **互斥**,不得同时为 `true` |
|
|
101
|
+
| `hiddenDefaultNotice` | `boolean` | `false` | `true` 时关闭默认 UI,仍检查并派发 `web_update_notice`,供业务自定义 UI。与 `disableNotification` **互斥**,不得同时为 `true` |
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
通知模式三选一:两者均不开启(默认 UI)/ 仅 `disableNotification` / 仅 `hiddenDefaultNotice`。
|
|
105
|
+
|
|
106
|
+
### `check`
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
| 字段 | 类型 | 默认 | 说明 |
|
|
110
|
+
| ----------------- | --------- | ---------------- | ------------------------------ |
|
|
111
|
+
| `interval` | `number` | `10 * 60 * 1000` | 轮询间隔(毫秒);`<= 0` 不轮询 |
|
|
112
|
+
| `onWindowActive` | `boolean` | `true` | 窗口重新获得焦点时检查 |
|
|
113
|
+
| `onTabVisible` | `boolean` | `true` | 标签页从隐藏变为可见时检查 |
|
|
114
|
+
| `onResourceError` | `boolean` | `true` | 静态资源加载失败时检查(用于发现发版后旧 chunk 失效) |
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
### `microApp`
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
| 字段 | 类型 | 默认 | 说明 |
|
|
123
|
+
| --------- | --------- | --- | ------------------------------------------- |
|
|
124
|
+
| `enabled` | `boolean` | — | 是否启用微前端口径;为 `true` 时需配合 Host `setActiveApp` |
|
|
125
|
+
| `appId` | `string` | — | 当前应用 ID;仅当该 ID 为 active app 时才会检查 / 通知 |
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
### `themeAdapter`
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
| 字段 | 类型 | 默认 | 说明 |
|
|
134
|
+
| -------------- | ------- | -------------------------------- | -------- |
|
|
135
|
+
| `type` | `'antd' | 'cssVariable'` | `'antd'` |
|
|
136
|
+
| `primaryColor` | `string | { light: string; dark: string }` | — |
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
### `locale`
|
|
142
|
+
|
|
143
|
+
按语言覆盖文案,键为 `'zh_CN' | 'en_US'`,值为部分字段:
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
| 字段 | 说明 |
|
|
147
|
+
| ------------------- | ---------- |
|
|
148
|
+
| `title` | 通知标题 |
|
|
149
|
+
| `description` | 可选更新时的说明文案 |
|
|
150
|
+
| `buttonText` | 「立即刷新」按钮文案 |
|
|
151
|
+
| `dismissButtonText` | 「稍后」按钮文案 |
|
|
152
|
+
| `forcedDescription` | 强制更新正文 |
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
createUpdateNotice({
|
|
157
|
+
versionBase: '/admin/',
|
|
158
|
+
check: { interval: 5 * 60 * 1000 },
|
|
159
|
+
placement: 'bottomRight',
|
|
160
|
+
forcedUpdate: false,
|
|
161
|
+
themeAdapter: { type: 'antd' },
|
|
162
|
+
locale: {
|
|
163
|
+
zh_CN: { title: '发现新版本', buttonText: '立即刷新' },
|
|
164
|
+
en_US: { title: 'Update available', buttonText: 'Refresh' },
|
|
165
|
+
},
|
|
166
|
+
})
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
## `VersionPluginOptions`
|
|
172
|
+
|
|
173
|
+
构建侧配置,传给 `vitePluginVersion(options?)` / `defaultPluginVersion(options?)`。只生成 `{outDir}/update-notice/version.json`,不注入 HTML / 脚本。Runtime **不**配置这些字段。
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
| 字段 | 类型 | 默认 | 说明 |
|
|
177
|
+
| ------------- | ------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
178
|
+
| `versionType` | `'timestamp' | 'gitcommit' | 'version'` |
|
|
179
|
+
| `outDir` | `string` | 见下 | 产物根目录,最终写出 `{outDir}/update-notice/version.json`。`vitePluginVersion` 未配置时读 Vite `build.outDir`;`defaultPluginVersion` 未配置时为 `'dist'` |
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
### `versionType`
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
| 值 | 说明 |
|
|
188
|
+
| ----------- | ------------------------------------------------------------- |
|
|
189
|
+
| `timestamp` | 构建时间戳(`Date.now()`),默认推荐 |
|
|
190
|
+
| `gitcommit` | 短 Git Commit(`git rev-parse --short HEAD`);获取失败时降级为 timestamp |
|
|
191
|
+
| `version` | 当前 `package.json` 的 `version`;获取失败时降级为 timestamp |
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
// vite.config.ts
|
|
196
|
+
vitePluginVersion({
|
|
197
|
+
versionType: 'gitcommit',
|
|
198
|
+
// outDir 一般可省略,自动用 Vite build.outDir
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
// 其他构建工具
|
|
202
|
+
await defaultPluginVersion({
|
|
203
|
+
versionType: 'version',
|
|
204
|
+
outDir: 'build',
|
|
205
|
+
})
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
69
210
|
## 本地示例
|
|
70
211
|
|
|
71
212
|
```bash
|
|
@@ -74,4 +215,4 @@ pnpm build
|
|
|
74
215
|
pnpm dev:vite # Host http://localhost:7100 · 单体 http://localhost:7103
|
|
75
216
|
```
|
|
76
217
|
|
|
77
|
-
更多示例见 [docs/examples.md](./docs/examples.md)。
|
|
218
|
+
更多示例见 [docs/examples.md](./docs/examples.md)。
|
package/dist/index.cjs
CHANGED
|
@@ -317,6 +317,7 @@ var UpdateNoticeRuntime = class {
|
|
|
317
317
|
const check = this.options.check ?? {};
|
|
318
318
|
const checkInterval = check.interval ?? DEFAULT_CHECK_INTERVAL;
|
|
319
319
|
const onWindowActive = check.onWindowActive !== false;
|
|
320
|
+
const onTabVisible = check.onTabVisible !== false;
|
|
320
321
|
const onResourceError = check.onResourceError !== false;
|
|
321
322
|
const checkImmediately = !this.options.microApp?.enabled;
|
|
322
323
|
const run = () => this.checkUpdate();
|
|
@@ -335,7 +336,7 @@ var UpdateNoticeRuntime = class {
|
|
|
335
336
|
if (document.visibilityState === "visible") {
|
|
336
337
|
startPolling();
|
|
337
338
|
flushPending();
|
|
338
|
-
if (
|
|
339
|
+
if (onTabVisible) run();
|
|
339
340
|
} else if (this.intervalId) {
|
|
340
341
|
clearInterval(this.intervalId);
|
|
341
342
|
this.intervalId = void 0;
|
|
@@ -397,7 +398,7 @@ var PRESET_LOCALE = {
|
|
|
397
398
|
};
|
|
398
399
|
function resolveNotificationCopy(options, locale) {
|
|
399
400
|
const builtin = PRESET_LOCALE[locale] ?? PRESET_LOCALE.zh_CN;
|
|
400
|
-
const fromData = options.locale?.
|
|
401
|
+
const fromData = options.locale?.[locale] ?? {};
|
|
401
402
|
return {
|
|
402
403
|
title: fromData.title ?? builtin.title,
|
|
403
404
|
description: fromData.description ?? builtin.description,
|
|
@@ -417,8 +418,8 @@ var DEFAULT_NOTICE_CSS = `
|
|
|
417
418
|
--update-icon-color: rgba(0, 0, 0, 0.45);
|
|
418
419
|
--update-icon-hover: rgba(0, 0, 0, 0.88);
|
|
419
420
|
--update-btn-hover-bg: rgba(0, 0, 0, 0.06);
|
|
420
|
-
--update-primary: #
|
|
421
|
-
--update-primary-hover: #
|
|
421
|
+
--update-primary: #4096ff;
|
|
422
|
+
--update-primary-hover: #69b1ff;
|
|
422
423
|
--update-mask: rgba(0, 0, 0, 0.45);
|
|
423
424
|
--update-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12),
|
|
424
425
|
0 9px 28px 8px rgba(0, 0, 0, 0.05);
|
|
@@ -431,8 +432,8 @@ var DEFAULT_NOTICE_CSS = `
|
|
|
431
432
|
--update-icon-color: rgba(255, 255, 255, 0.45);
|
|
432
433
|
--update-icon-hover: rgba(255, 255, 255, 0.85);
|
|
433
434
|
--update-btn-hover-bg: rgba(255, 255, 255, 0.08);
|
|
434
|
-
--update-primary: #
|
|
435
|
-
--update-primary-hover: #
|
|
435
|
+
--update-primary: #3c89e8;
|
|
436
|
+
--update-primary-hover: #65a9f3;
|
|
436
437
|
--update-mask: rgba(0, 0, 0, 0.65);
|
|
437
438
|
--update-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.32), 0 3px 6px -4px rgba(0, 0, 0, 0.48),
|
|
438
439
|
0 9px 28px 8px rgba(0, 0, 0, 0.2);
|
|
@@ -450,7 +451,7 @@ var DEFAULT_NOTICE_CSS = `
|
|
|
450
451
|
}
|
|
451
452
|
|
|
452
453
|
.cdfrd-update-notice:not(.cdfrd-update-notice--forced) {
|
|
453
|
-
width:
|
|
454
|
+
width: 316px;
|
|
454
455
|
}
|
|
455
456
|
|
|
456
457
|
.cdfrd-update-notice-panel {
|
|
@@ -472,6 +473,9 @@ var DEFAULT_NOTICE_CSS = `
|
|
|
472
473
|
font-weight: 600;
|
|
473
474
|
line-height: 1.5;
|
|
474
475
|
color: var(--update-text);
|
|
476
|
+
overflow: hidden;
|
|
477
|
+
white-space: nowrap;
|
|
478
|
+
text-overflow: ellipsis;
|
|
475
479
|
}
|
|
476
480
|
|
|
477
481
|
.cdfrd-update-notice-desc {
|
|
@@ -480,6 +484,11 @@ var DEFAULT_NOTICE_CSS = `
|
|
|
480
484
|
font-size: 14px;
|
|
481
485
|
line-height: 1.5714;
|
|
482
486
|
color: var(--update-text-secondary);
|
|
487
|
+
display: -webkit-box;
|
|
488
|
+
-webkit-box-orient: vertical;
|
|
489
|
+
-webkit-line-clamp: 3;
|
|
490
|
+
overflow: hidden;
|
|
491
|
+
text-overflow: ellipsis;
|
|
483
492
|
}
|
|
484
493
|
|
|
485
494
|
/* Close \u2014 slightly larger than default antd notice close */
|
|
@@ -526,7 +535,10 @@ var DEFAULT_NOTICE_CSS = `
|
|
|
526
535
|
border-radius: 4px;
|
|
527
536
|
background: transparent;
|
|
528
537
|
box-sizing: border-box;
|
|
538
|
+
max-width: 120px;
|
|
539
|
+
overflow: hidden;
|
|
529
540
|
white-space: nowrap;
|
|
541
|
+
text-overflow: ellipsis;
|
|
530
542
|
transition: all 0.2s;
|
|
531
543
|
}
|
|
532
544
|
|
|
@@ -573,7 +585,7 @@ var DEFAULT_NOTICE_CSS = `
|
|
|
573
585
|
|
|
574
586
|
.cdfrd-update-notice--forced .cdfrd-update-notice-panel {
|
|
575
587
|
width: max-content;
|
|
576
|
-
max-width: min(
|
|
588
|
+
max-width: min(336px, calc(100vw - 48px));
|
|
577
589
|
padding: 20px 24px;
|
|
578
590
|
}
|
|
579
591
|
|
|
@@ -732,9 +744,9 @@ function tryResolveAntdPrimaryColor(options) {
|
|
|
732
744
|
}
|
|
733
745
|
function resolveCssVariablePrimary(config, theme) {
|
|
734
746
|
const primary = config?.primaryColor;
|
|
735
|
-
if (!primary) return
|
|
747
|
+
if (!primary) return "";
|
|
736
748
|
if (typeof primary === "string") return primary;
|
|
737
|
-
return primary[theme] || primary.light ||
|
|
749
|
+
return primary[theme] || primary.light || "";
|
|
738
750
|
}
|
|
739
751
|
function scheduleFrame(cb) {
|
|
740
752
|
if (typeof requestAnimationFrame === "function") {
|
|
@@ -1040,10 +1052,45 @@ function el(tag, className, text) {
|
|
|
1040
1052
|
if (text !== void 0) node.textContent = text;
|
|
1041
1053
|
return node;
|
|
1042
1054
|
}
|
|
1055
|
+
function lightenPrimaryForHover(primary, amount = 0.22) {
|
|
1056
|
+
const trimmed = primary.trim();
|
|
1057
|
+
const hex = trimmed.match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i);
|
|
1058
|
+
let r;
|
|
1059
|
+
let g;
|
|
1060
|
+
let b;
|
|
1061
|
+
if (hex) {
|
|
1062
|
+
const h = hex[1];
|
|
1063
|
+
if (h.length === 3) {
|
|
1064
|
+
r = parseInt(h[0] + h[0], 16);
|
|
1065
|
+
g = parseInt(h[1] + h[1], 16);
|
|
1066
|
+
b = parseInt(h[2] + h[2], 16);
|
|
1067
|
+
} else {
|
|
1068
|
+
r = parseInt(h.slice(0, 2), 16);
|
|
1069
|
+
g = parseInt(h.slice(2, 4), 16);
|
|
1070
|
+
b = parseInt(h.slice(4, 6), 16);
|
|
1071
|
+
}
|
|
1072
|
+
} else {
|
|
1073
|
+
const rgb = trimmed.match(
|
|
1074
|
+
/^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)(?:\s*,\s*[\d.]+)?\s*\)$/i
|
|
1075
|
+
);
|
|
1076
|
+
if (!rgb) return primary;
|
|
1077
|
+
r = Number(rgb[1]);
|
|
1078
|
+
g = Number(rgb[2]);
|
|
1079
|
+
b = Number(rgb[3]);
|
|
1080
|
+
}
|
|
1081
|
+
const mix = (c) => Math.round(c + (255 - c) * amount);
|
|
1082
|
+
const toHex = (c) => mix(c).toString(16).padStart(2, "0");
|
|
1083
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
1084
|
+
}
|
|
1043
1085
|
function applyPrimaryToNode(node, primary) {
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1086
|
+
const el2 = node;
|
|
1087
|
+
if (!primary) {
|
|
1088
|
+
el2.style.removeProperty("--update-primary");
|
|
1089
|
+
el2.style.removeProperty("--update-primary-hover");
|
|
1090
|
+
return;
|
|
1091
|
+
}
|
|
1092
|
+
el2.style.setProperty("--update-primary", primary);
|
|
1093
|
+
el2.style.setProperty("--update-primary-hover", lightenPrimaryForHover(primary));
|
|
1047
1094
|
}
|
|
1048
1095
|
function applyTheme(theme) {
|
|
1049
1096
|
ensureDefaultStyles();
|
|
@@ -1104,14 +1151,14 @@ function showDefaultNotice(options) {
|
|
|
1104
1151
|
const placement = options.options.placement ?? "topRight";
|
|
1105
1152
|
const forced = options.options.forcedUpdate === true;
|
|
1106
1153
|
const theme = options.theme ?? "light";
|
|
1107
|
-
const primary = options.primaryColor
|
|
1154
|
+
const primary = options.primaryColor ?? currentPrimary;
|
|
1108
1155
|
const wrap = document.createElement("div");
|
|
1109
1156
|
wrap.className = forced ? "cdfrd-update-notice cdfrd-update-notice--forced" : "cdfrd-update-notice";
|
|
1110
1157
|
wrap.setAttribute("data-update-notice-theme", theme);
|
|
1111
1158
|
if (!forced) {
|
|
1112
1159
|
wrap.style.cssText = PLACEMENT_STYLES[placement] ?? PLACEMENT_STYLES.topRight;
|
|
1113
1160
|
}
|
|
1114
|
-
|
|
1161
|
+
applyPrimaryToNode(wrap, primary);
|
|
1115
1162
|
const panel = el("div", "cdfrd-update-notice-panel");
|
|
1116
1163
|
if (forced) {
|
|
1117
1164
|
panel.appendChild(el("div", "cdfrd-update-notice-title", copy.forcedTitle));
|
|
@@ -1196,7 +1243,6 @@ var UpdateNoticeManager = class _UpdateNoticeManager {
|
|
|
1196
1243
|
validateOptions(options);
|
|
1197
1244
|
if (isFirstCreate) {
|
|
1198
1245
|
this.themeAdapter = options.themeAdapter;
|
|
1199
|
-
if (options.locale?.default) this.locale = options.locale.default;
|
|
1200
1246
|
applyTheme(this.theme);
|
|
1201
1247
|
this.startThemeWatch();
|
|
1202
1248
|
}
|