unplugin-version-injector 2.1.1 → 2.2.1
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 +185 -18
- package/README.zh-CN.md +170 -3
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +355 -0
- package/dist/index.mjs +344 -0
- package/dist/rolldown.d.mts +6 -0
- package/dist/rolldown.d.ts +6 -0
- package/dist/rolldown.js +352 -0
- package/dist/rolldown.mjs +345 -0
- package/dist/rollup.d.mts +4 -10
- package/dist/rollup.d.ts +4 -10
- package/dist/rollup.js +307 -43
- package/dist/rollup.mjs +307 -43
- package/dist/rspack.d.mts +6 -0
- package/dist/rspack.d.ts +6 -0
- package/dist/rspack.js +352 -0
- package/dist/rspack.mjs +345 -0
- package/dist/types-Cc-nzIS0.d.mts +26 -0
- package/dist/types-Cc-nzIS0.d.ts +26 -0
- package/dist/vite.d.mts +4 -3
- package/dist/vite.d.ts +4 -3
- package/dist/vite.js +308 -36
- package/dist/vite.mjs +308 -36
- package/dist/webpack.d.mts +4 -5
- package/dist/webpack.d.ts +4 -5
- package/dist/webpack.js +307 -2744
- package/dist/webpack.mjs +307 -2744
- package/package.json +101 -27
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## 📌 Introduction
|
|
8
8
|
|
|
9
|
-
`unplugin-version-injector` is a lightweight plugin that automatically injects **version** and **build timestamp** into all HTML files. It supports **Webpack 4/5**, **
|
|
9
|
+
`unplugin-version-injector` is a lightweight [unplugin](https://github.com/unjs/unplugin)-based plugin that automatically injects **version** and **build timestamp** into all HTML files. It supports **Vite**, **Webpack 4/5**, **Rspack**, **Rollup** and **Rolldown**, and works seamlessly with both **SPA** and **MPA** projects.
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
@@ -14,20 +14,25 @@
|
|
|
14
14
|
|
|
15
15
|
✅ Injects `<meta name="version">` and `<meta name="project">` into the `<head>`
|
|
16
16
|
✅ Injects `<script>` into the `<body>` to log version, name, and build time
|
|
17
|
-
✅ Supports Webpack 4
|
|
17
|
+
✅ Supports Vite, Webpack 4/5, Rspack, Rollup, Rolldown
|
|
18
18
|
✅ Fully compatible with Multi-Page Applications (MPA)
|
|
19
19
|
✅ Customizable version, project name, date format, and theme-based console styling
|
|
20
|
+
✅ Date format supports dayjs-style patterns (`YYYY-MM-DD HH:mm:ss`) with zero extra dependencies
|
|
21
|
+
✅ Optional: attach a version header (`X-Client-Version`) to `fetch` / `XMLHttpRequest` requests to identify clients in backend logs
|
|
20
22
|
|
|
21
23
|
---
|
|
22
24
|
|
|
23
25
|
## 📦 Installation
|
|
24
26
|
|
|
25
27
|
```bash
|
|
26
|
-
# Using Yarn
|
|
27
|
-
yarn add -D unplugin-version-injector
|
|
28
|
-
|
|
29
28
|
# Using npm
|
|
30
29
|
npm install -D unplugin-version-injector
|
|
30
|
+
|
|
31
|
+
# Using yarn
|
|
32
|
+
yarn add -D unplugin-version-injector
|
|
33
|
+
|
|
34
|
+
# Using pnpm
|
|
35
|
+
pnpm add -D unplugin-version-injector
|
|
31
36
|
```
|
|
32
37
|
|
|
33
38
|
---
|
|
@@ -37,6 +42,7 @@ npm install -D unplugin-version-injector
|
|
|
37
42
|
### 📌 Vite
|
|
38
43
|
|
|
39
44
|
```ts
|
|
45
|
+
// vite.config.ts
|
|
40
46
|
import versionInjector from 'unplugin-version-injector/vite';
|
|
41
47
|
|
|
42
48
|
export default {
|
|
@@ -44,11 +50,10 @@ export default {
|
|
|
44
50
|
};
|
|
45
51
|
```
|
|
46
52
|
|
|
47
|
-
---
|
|
48
|
-
|
|
49
53
|
### 📌 Webpack 4/5
|
|
50
54
|
|
|
51
55
|
```js
|
|
56
|
+
// webpack.config.js
|
|
52
57
|
const versionInjector = require('unplugin-version-injector/webpack');
|
|
53
58
|
|
|
54
59
|
module.exports = {
|
|
@@ -60,11 +65,21 @@ module.exports = {
|
|
|
60
65
|
};
|
|
61
66
|
```
|
|
62
67
|
|
|
63
|
-
|
|
68
|
+
### 📌 Rspack
|
|
69
|
+
|
|
70
|
+
```js
|
|
71
|
+
// rspack.config.js
|
|
72
|
+
const versionInjector = require('unplugin-version-injector/rspack');
|
|
73
|
+
|
|
74
|
+
module.exports = {
|
|
75
|
+
plugins: [versionInjector()],
|
|
76
|
+
};
|
|
77
|
+
```
|
|
64
78
|
|
|
65
79
|
### 📌 Rollup
|
|
66
80
|
|
|
67
81
|
```js
|
|
82
|
+
// rollup.config.js
|
|
68
83
|
import versionInjector from 'unplugin-version-injector/rollup';
|
|
69
84
|
|
|
70
85
|
export default {
|
|
@@ -72,6 +87,17 @@ export default {
|
|
|
72
87
|
};
|
|
73
88
|
```
|
|
74
89
|
|
|
90
|
+
### 📌 Rolldown
|
|
91
|
+
|
|
92
|
+
```js
|
|
93
|
+
// rolldown.config.js
|
|
94
|
+
import versionInjector from 'unplugin-version-injector/rolldown';
|
|
95
|
+
|
|
96
|
+
export default {
|
|
97
|
+
plugins: [versionInjector()],
|
|
98
|
+
};
|
|
99
|
+
```
|
|
100
|
+
|
|
75
101
|
---
|
|
76
102
|
|
|
77
103
|
## 🧪 Example Output
|
|
@@ -85,9 +111,9 @@ In your final HTML output:
|
|
|
85
111
|
</head>
|
|
86
112
|
<body>
|
|
87
113
|
<script data-injected="unplugin-version-injector">
|
|
88
|
-
console
|
|
89
|
-
|
|
90
|
-
|
|
114
|
+
// console badges:
|
|
115
|
+
// my-project@1.2.3
|
|
116
|
+
// Build Time: 2024-04-01T12:00:00.000Z
|
|
91
117
|
</script>
|
|
92
118
|
</body>
|
|
93
119
|
```
|
|
@@ -96,12 +122,153 @@ In your final HTML output:
|
|
|
96
122
|
|
|
97
123
|
## 🔧 Configuration Options
|
|
98
124
|
|
|
99
|
-
| Option
|
|
100
|
-
|
|
101
|
-
| `version`
|
|
102
|
-
| `name`
|
|
103
|
-
| `log`
|
|
104
|
-
| `
|
|
125
|
+
| Option | Type | Description | Default |
|
|
126
|
+
|------------------|-----------------------------------|--------------------------------------------------------|------------------------|
|
|
127
|
+
| `version` | `string` | Custom version number | Read from package.json |
|
|
128
|
+
| `name` | `string` | Custom project name | Read from package.json |
|
|
129
|
+
| `log` | `boolean` | Whether to inject the console log script | `true` |
|
|
130
|
+
| `formatDate` | `string \| ((date: Date) => string)` | Custom build time format: a dayjs-style pattern (e.g. `'YYYY-MM-DD HH:mm:ss'`) or a function | ISO 8601 format |
|
|
131
|
+
| `requestHeaders` | `boolean \| RequestHeadersOptions` | Attach version/build-time headers to outgoing requests | `false` |
|
|
132
|
+
|
|
133
|
+
> `version` and `name` can be provided independently — whichever is missing falls back to the nearest `package.json`.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## 📅 Formatting build time (`formatDate`)
|
|
138
|
+
|
|
139
|
+
`formatDate` accepts two forms, and applies to both the **console banner** and the **`X-Client-Build-Time` header**:
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
// 1) dayjs-style pattern (built-in lightweight impl, no dayjs needed)
|
|
143
|
+
versionInjector({ formatDate: 'YYYY-MM-DD HH:mm:ss' }); // 2024-04-01 12:30:45
|
|
144
|
+
|
|
145
|
+
// 2) custom function
|
|
146
|
+
versionInjector({ formatDate: (date) => date.getTime().toString() }); // timestamp
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Supported tokens: `YYYY YY MMMM MMM MM M DD D dddd ddd dd d HH H hh h mm m ss s SSS SS S A a`.
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## 📡 Request Headers (identify clients in backend logs)
|
|
154
|
+
|
|
155
|
+
Enable `requestHeaders` to patch `window.fetch` and `XMLHttpRequest` so requests carry the client version and build time — making it trivial to tell which client build produced a request in backend/API logs. Two headers are injected by default:
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
X-Client-Version: my-app/1.2.3
|
|
159
|
+
X-Client-Build-Time: 2024-04-01 12:00:00
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
> Because it patches `fetch` / `XMLHttpRequest`, **axios and most HTTP clients work automatically**. `navigator.sendBeacon` and WebSocket connections cannot carry custom headers and are not covered.
|
|
163
|
+
|
|
164
|
+
### `RequestHeadersOptions`
|
|
165
|
+
|
|
166
|
+
| Option | Type | Description | Default |
|
|
167
|
+
|---|---|---|---|
|
|
168
|
+
| `versionHeaderName` | `string` | Version header name; value is `${name}/${version}` | `'X-Client-Version'` |
|
|
169
|
+
| `buildTimeHeaderName` | `string` | Build-time header name; value is the `formatDate` output | `'X-Client-Build-Time'` |
|
|
170
|
+
| `include` | `(string \| RegExp)[]` | Extra **cross-origin** allowlist: string = URL prefix, RegExp = full-URL test. **Same-origin requests are always injected** | `[]` |
|
|
171
|
+
|
|
172
|
+
### Scenario 1: same-origin (simplest)
|
|
173
|
+
|
|
174
|
+
Page and API share an origin, or you use a dev-server proxy (requests hit `/api`, which the browser treats as same-origin):
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
versionInjector({ requestHeaders: true }); // true = defaults, same-origin only
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Scenario 2: custom header names
|
|
181
|
+
|
|
182
|
+
```ts
|
|
183
|
+
versionInjector({
|
|
184
|
+
requestHeaders: {
|
|
185
|
+
versionHeaderName: 'X-App-Version',
|
|
186
|
+
buildTimeHeaderName: 'X-App-Build',
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Scenario 3: a single cross-origin API (most common in prod)
|
|
192
|
+
|
|
193
|
+
Front end and API are on different origins — add the API origin to `include` (string = URL prefix):
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
versionInjector({
|
|
197
|
+
requestHeaders: { include: ['https://api.example.com'] },
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Scenario 4: multiple cross-origin APIs / RegExp
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
versionInjector({
|
|
205
|
+
requestHeaders: {
|
|
206
|
+
include: [
|
|
207
|
+
'https://api.example.com',
|
|
208
|
+
'https://auth.example.com',
|
|
209
|
+
/^https:\/\/[^/]*\.example\.com\//, // any *.example.com subdomain
|
|
210
|
+
],
|
|
211
|
+
},
|
|
212
|
+
});
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Scenario 5: Monorepo + all cross-origin (the trickiest) ⭐
|
|
216
|
+
|
|
217
|
+
Many packages share one build config, and each app talks to cross-origin APIs that differ per environment (dev / sandbox / prod). Two keys:
|
|
218
|
+
|
|
219
|
+
**1. Write `include` once in the shared root config** — every package inherits it (put the plugin in the shared `configureWebpack` / `vite` config).
|
|
220
|
+
|
|
221
|
+
**2. Don't hardcode origins — build them from env vars.** Each app's `.env.*` usually already defines its API origins:
|
|
222
|
+
|
|
223
|
+
```js
|
|
224
|
+
// shared root build config (webpack example)
|
|
225
|
+
const versionInjector = require('unplugin-version-injector/webpack');
|
|
226
|
+
|
|
227
|
+
// provided by each app / each environment's .env
|
|
228
|
+
const apiOrigins = [
|
|
229
|
+
process.env.VUE_APP_API_ORIGIN,
|
|
230
|
+
process.env.VUE_APP_SDK_API_ORIGIN,
|
|
231
|
+
process.env.VUE_APP_USER_API_ORIGIN,
|
|
232
|
+
].filter(Boolean);
|
|
233
|
+
|
|
234
|
+
module.exports = {
|
|
235
|
+
configureWebpack: {
|
|
236
|
+
plugins: [
|
|
237
|
+
versionInjector({ requestHeaders: { include: apiOrigins } }),
|
|
238
|
+
],
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
dev / sandbox / prod each get the right origins automatically — no giant hardcoded list.
|
|
244
|
+
|
|
245
|
+
If all APIs live under a few fixed base domains, a single RegExp also works (new subdomains match automatically):
|
|
246
|
+
|
|
247
|
+
```ts
|
|
248
|
+
versionInjector({
|
|
249
|
+
requestHeaders: {
|
|
250
|
+
include: [/^https:\/\/[^/]*\.(example\.io|example\.dev|sandbox-example\.com)\//],
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
> Only include API origins you actually `fetch`/`XHR` **and** whose CORS you control. Don't add CDNs or third-party SDK script hosts — that only triggers preflights and can break asset loading.
|
|
256
|
+
|
|
257
|
+
### ⚠️ Cross-origin requires backend cooperation (CORS preflight)
|
|
258
|
+
|
|
259
|
+
Custom headers on cross-origin requests trigger an `OPTIONS` preflight. **Every** API service matched by `include` must allow the two headers, or the browser blocks the request:
|
|
260
|
+
|
|
261
|
+
```
|
|
262
|
+
Access-Control-Allow-Headers: X-Client-Version, X-Client-Build-Time
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
This is exactly why cross-origin injection is opt-in via `include` rather than on by default.
|
|
266
|
+
|
|
267
|
+
### 🔍 Same-origin or cross-origin?
|
|
268
|
+
|
|
269
|
+
Open the browser Network tab and look at the request's **real URL**:
|
|
270
|
+
- `http://localhost:9040/api/...` (via dev proxy) → **same-origin**, `requestHeaders: true` is enough, no `include`.
|
|
271
|
+
- `https://api.xxx.com/...` (direct) → **cross-origin**, must be in `include` + backend must allow the headers.
|
|
105
272
|
|
|
106
273
|
---
|
|
107
274
|
|
|
@@ -121,4 +288,4 @@ MIT License © 2024 [Nian YI](https://github.com/nianyi778)
|
|
|
121
288
|
|
|
122
289
|
---
|
|
123
290
|
|
|
124
|
-
🔥 `unplugin-version-injector` – the simplest way to track version and build info!
|
|
291
|
+
🔥 `unplugin-version-injector` – the simplest way to track version and build info!
|
package/README.zh-CN.md
CHANGED
|
@@ -5,17 +5,19 @@
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
## **📌 插件简介**
|
|
8
|
-
`unplugin-version-injector`
|
|
8
|
+
`unplugin-version-injector` 是一个基于 [unplugin](https://github.com/unjs/unplugin) 的轻量级插件,可在构建时自动向所有 HTML 文件注入 **版本号**、**构建时间戳** 和 **项目名**。支持 **Vite、Webpack 4/5、Rspack、Rollup 和 Rolldown**,适用于 **SPA / MPA 项目**。
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
## **✨ 功能亮点**
|
|
13
13
|
✅ 自动注入 `<meta name="version">` 和 `<meta name="project">` 到 HTML `<head>`
|
|
14
14
|
✅ 自动注入 `<script>`,控制台输出 `项目名`、`版本号` 和 `构建时间`
|
|
15
|
-
✅ 支持 Webpack 4
|
|
15
|
+
✅ 支持 Vite、Webpack 4/5、Rspack、Rollup、Rolldown
|
|
16
16
|
✅ 完美兼容多页面应用(MPA)
|
|
17
17
|
✅ 支持自定义版本号、项目名、时间格式,默认读取 `package.json`
|
|
18
18
|
✅ 控制台输出支持自动适配深/浅主题配色
|
|
19
|
+
✅ 时间格式支持 dayjs 风格字符串(`YYYY-MM-DD HH:mm:ss`),零额外依赖
|
|
20
|
+
✅ 可选:给 `fetch` / `XMLHttpRequest` 请求自动注入版本请求头(`X-Client-Version`),在后端日志中定位客户端版本
|
|
19
21
|
|
|
20
22
|
---
|
|
21
23
|
|
|
@@ -61,6 +63,18 @@ module.exports = {
|
|
|
61
63
|
|
|
62
64
|
---
|
|
63
65
|
|
|
66
|
+
### **📌 Rspack**
|
|
67
|
+
`rspack.config.js` 中配置:
|
|
68
|
+
```js
|
|
69
|
+
const versionInjector = require('unplugin-version-injector/rspack');
|
|
70
|
+
|
|
71
|
+
module.exports = {
|
|
72
|
+
plugins: [versionInjector()],
|
|
73
|
+
};
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
64
78
|
### **📌 Rollup**
|
|
65
79
|
`rollup.config.js` 中配置:
|
|
66
80
|
```js
|
|
@@ -73,6 +87,18 @@ export default {
|
|
|
73
87
|
|
|
74
88
|
---
|
|
75
89
|
|
|
90
|
+
### **📌 Rolldown**
|
|
91
|
+
`rolldown.config.js` 中配置:
|
|
92
|
+
```js
|
|
93
|
+
import versionInjector from 'unplugin-version-injector/rolldown';
|
|
94
|
+
|
|
95
|
+
export default {
|
|
96
|
+
plugins: [versionInjector()],
|
|
97
|
+
};
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
76
102
|
## **🧪 示例输出**
|
|
77
103
|
|
|
78
104
|
构建后的 HTML 文件中将自动注入:
|
|
@@ -107,7 +133,148 @@ export default {
|
|
|
107
133
|
| `version` | `string` | 自定义版本号 | 自动读取 package.json |
|
|
108
134
|
| `name` | `string` | 自定义项目名 | 自动读取 package.json |
|
|
109
135
|
| `log` | `boolean` | 是否输出控制台日志 | `true` |
|
|
110
|
-
| `formatDate` | `Date => string` |
|
|
136
|
+
| `formatDate` | `string \| ((date: Date) => string)` | 自定义构建时间格式:支持 dayjs 风格字符串(如 `'YYYY-MM-DD HH:mm:ss'`)或函数 | ISO 格式 |
|
|
137
|
+
| `requestHeaders` | `boolean \| RequestHeadersOptions` | 给发出的请求自动附加版本/构建时间请求头 | `false` |
|
|
138
|
+
|
|
139
|
+
> `version` 和 `name` 可以单独传入,缺失的一项会自动从最近的 `package.json` 读取。
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## **📅 构建时间格式化 `formatDate`**
|
|
144
|
+
|
|
145
|
+
`formatDate` 支持两种写法,同时作用于**控制台构建时间**和 **`X-Client-Build-Time` 请求头**:
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
// 1) dayjs 风格字符串(内置轻量实现,无需安装 dayjs)
|
|
149
|
+
versionInjector({ formatDate: 'YYYY-MM-DD HH:mm:ss' }); // 2024-04-01 12:30:45
|
|
150
|
+
|
|
151
|
+
// 2) 自定义函数
|
|
152
|
+
versionInjector({ formatDate: (date) => date.getTime().toString() }); // 时间戳
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
支持的 token:`YYYY YY MMMM MMM MM M DD D dddd ddd dd d HH H hh h mm m ss s SSS SS S A a`。
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## **📡 请求头注入(在后端日志中定位客户端版本)**
|
|
160
|
+
|
|
161
|
+
开启 `requestHeaders` 后,插件会在页面最前面 patch `window.fetch` 和 `XMLHttpRequest`,让请求自动带上版本与构建时间——排查前后端日志时,一眼就能看出是哪个客户端、哪个版本发出的请求。默认注入两个头:
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
X-Client-Version: my-app/1.2.3
|
|
165
|
+
X-Client-Build-Time: 2024-04-01 12:00:00
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
> 底层是 patch `fetch` / `XMLHttpRequest`,所以 **axios、umi-request 等主流库都自动生效**;`navigator.sendBeacon` 和 WebSocket 无法携带自定义头,不在覆盖范围。
|
|
169
|
+
|
|
170
|
+
### 子配置 `RequestHeadersOptions`
|
|
171
|
+
|
|
172
|
+
| 选项 | 类型 | 说明 | 默认值 |
|
|
173
|
+
|---|---|---|---|
|
|
174
|
+
| `versionHeaderName` | `string` | 版本头名称,值为 `${name}/${version}` | `'X-Client-Version'` |
|
|
175
|
+
| `buildTimeHeaderName` | `string` | 构建时间头名称,值为 `formatDate` 的输出 | `'X-Client-Build-Time'` |
|
|
176
|
+
| `include` | `(string \| RegExp)[]` | 额外注入的**跨域**地址白名单:字符串按 URL 前缀匹配,正则按完整 URL 测试。**同源请求始终注入** | `[]` |
|
|
177
|
+
|
|
178
|
+
### 场景 1:同源请求(最简单)
|
|
179
|
+
|
|
180
|
+
页面与 API 同域,或本地走 dev-server 代理(请求发到 `/api`,浏览器视角是同源):
|
|
181
|
+
|
|
182
|
+
```ts
|
|
183
|
+
versionInjector({ requestHeaders: true }); // true = 默认配置,仅同源
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### 场景 2:自定义请求头名称
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
versionInjector({
|
|
190
|
+
requestHeaders: {
|
|
191
|
+
versionHeaderName: 'X-App-Version',
|
|
192
|
+
buildTimeHeaderName: 'X-App-Build',
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### 场景 3:单个跨域 API(生产最常见)
|
|
198
|
+
|
|
199
|
+
前端和 API 不同源,把 API 域名加进 `include`(字符串 = URL 前缀):
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
versionInjector({
|
|
203
|
+
requestHeaders: { include: ['https://api.example.com'] },
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### 场景 4:多个跨域 API / 正则批量匹配
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
versionInjector({
|
|
211
|
+
requestHeaders: {
|
|
212
|
+
include: [
|
|
213
|
+
'https://api.example.com',
|
|
214
|
+
'https://auth.example.com',
|
|
215
|
+
/^https:\/\/[^/]*\.example\.com\//, // 匹配 *.example.com 所有子域
|
|
216
|
+
],
|
|
217
|
+
},
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### 场景 5:Monorepo + 全跨域(最容易踩坑)⭐
|
|
222
|
+
|
|
223
|
+
多包共用一份构建配置、每个子应用又连不同环境(dev / sandbox / prod)的跨域 API——这是最难配的场景。两个关键点:
|
|
224
|
+
|
|
225
|
+
**① `include` 只需在共享的根配置里写一次**,所有子包继承即可(把插件放进共享的 `configureWebpack` / `vite` 配置)。
|
|
226
|
+
|
|
227
|
+
**② 域名随环境变化,别硬编码——用环境变量动态拼**。每个子应用的 `.env.*` 里通常已有 API 域名变量,直接读:
|
|
228
|
+
|
|
229
|
+
```js
|
|
230
|
+
// 共享的根构建配置(以 webpack 为例)
|
|
231
|
+
const versionInjector = require('unplugin-version-injector/webpack');
|
|
232
|
+
|
|
233
|
+
// 这些变量由各子应用 / 各环境的 .env 提供
|
|
234
|
+
const apiOrigins = [
|
|
235
|
+
process.env.VUE_APP_API_ORIGIN,
|
|
236
|
+
process.env.VUE_APP_SDK_API_ORIGIN,
|
|
237
|
+
process.env.VUE_APP_USER_API_ORIGIN,
|
|
238
|
+
].filter(Boolean); // 去掉未定义的
|
|
239
|
+
|
|
240
|
+
module.exports = {
|
|
241
|
+
configureWebpack: {
|
|
242
|
+
plugins: [
|
|
243
|
+
versionInjector({ requestHeaders: { include: apiOrigins } }),
|
|
244
|
+
],
|
|
245
|
+
},
|
|
246
|
+
};
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
这样 dev / sandbox / prod 各自带对应域名,不用维护一份大清单。
|
|
250
|
+
|
|
251
|
+
若所有 API 都在固定的几个主域名下,也可以直接用一条正则(新增子域自动命中):
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
versionInjector({
|
|
255
|
+
requestHeaders: {
|
|
256
|
+
include: [/^https:\/\/[^/]*\.(example\.io|example\.dev|sandbox-example\.com)\//],
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
> 只把**你自己发 fetch/XHR、且能改 CORS 的 API 域名**放进去。CDN、第三方 SDK 脚本域(你控制不了 CORS)不要加,否则只会触发预检导致资源加载失败。
|
|
262
|
+
|
|
263
|
+
### ⚠️ 跨域必读:后端要放行(CORS 预检)
|
|
264
|
+
|
|
265
|
+
给跨域请求加自定义头,浏览器会先发一个 `OPTIONS` 预检。`include` 命中的**每一个** API 服务都必须在响应里放行这两个头,否则请求会被浏览器拦掉:
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
Access-Control-Allow-Headers: X-Client-Version, X-Client-Build-Time
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
多后端场景要逐个确认。这也是跨域注入必须通过 `include` 显式开启、而非默认全开的原因。
|
|
272
|
+
|
|
273
|
+
### 🔍 怎么判断请求是同源还是跨域?
|
|
274
|
+
|
|
275
|
+
打开浏览器 Network,看请求的**真实 URL**:
|
|
276
|
+
- `http://localhost:9040/api/...`(走 dev 代理)→ **同源**,`requestHeaders: true` 就够,不用 `include`;
|
|
277
|
+
- `https://api.xxx.com/...`(直连)→ **跨域**,必须加进 `include` + 后端放行。
|
|
111
278
|
|
|
112
279
|
---
|
|
113
280
|
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { UnpluginInstance, UnpluginFactory } from 'unplugin';
|
|
2
|
+
import { V as VersionInjectorOptions } from './types-Cc-nzIS0.mjs';
|
|
3
|
+
export { R as RequestHeadersOptions } from './types-Cc-nzIS0.mjs';
|
|
4
|
+
|
|
5
|
+
declare const unpluginFactory: UnpluginFactory<VersionInjectorOptions | undefined>;
|
|
6
|
+
declare const VersionInjector: UnpluginInstance<VersionInjectorOptions | undefined>;
|
|
7
|
+
|
|
8
|
+
export { VersionInjector, VersionInjectorOptions, VersionInjector as default, unpluginFactory };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { UnpluginInstance, UnpluginFactory } from 'unplugin';
|
|
2
|
+
import { V as VersionInjectorOptions } from './types-Cc-nzIS0.js';
|
|
3
|
+
export { R as RequestHeadersOptions } from './types-Cc-nzIS0.js';
|
|
4
|
+
|
|
5
|
+
declare const unpluginFactory: UnpluginFactory<VersionInjectorOptions | undefined>;
|
|
6
|
+
declare const VersionInjector: UnpluginInstance<VersionInjectorOptions | undefined>;
|
|
7
|
+
|
|
8
|
+
export { VersionInjector, VersionInjectorOptions, VersionInjector as default, unpluginFactory };
|