vite-plugin-build-version-file 0.1.10 → 0.1.12

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 CHANGED
@@ -7,6 +7,7 @@
7
7
  - 开发态通过 dev server 提供 `version.json`
8
8
  - 构建后在输出目录生成 `version.json`
9
9
  - 普通 Vite HTML 自动注入 `window["__VERSION__"]`
10
+ - 可选通过 `define` 将同一份 payload 编译进 JS 产物
10
11
  - VitePress 可通过顶层 `transformHtml` 注入同一份版本信息
11
12
  - 支持自定义版本号、输出文件名、全局变量名、时区和额外字段
12
13
 
@@ -78,6 +79,8 @@ export default defineConfig({
78
79
 
79
80
  注意:这里必须复用同一个 `buildVersion` 实例。不要分别调用两次 `buildVersionPlugin()`,否则 `transformHtml` 拿不到 Vite 插件阶段生成的 payload。
80
81
 
82
+ VitePress 构建会包含 client bundle 和 SSR bundle。插件只在最终静态产物 bundle 输出 `version.json`,避免同一次 VitePress build 出现重复日志或重复 emit。
83
+
81
84
  ## 默认行为
82
85
 
83
86
  默认配置下,插件会做这些事:
@@ -125,6 +128,7 @@ type BuildVersionContext = {
125
128
  type BuildVersionPluginOptions = {
126
129
  filename?: string
127
130
  globalName?: string
131
+ defineName?: string | false
128
132
  injectToHtml?: boolean
129
133
  timeZone?: string
130
134
  version?: string | number | ((ctx: BuildVersionContext) => string | number)
@@ -178,6 +182,36 @@ dist/meta/version.json
178
182
 
179
183
  这里注入的是完整 payload 对象,不是单独版本字符串。
180
184
 
185
+ ### `defineName`
186
+
187
+ - 类型:`string | false`
188
+ - 默认值:`"__VERSION__"`
189
+ - 作用:控制是否通过 Vite `define` 将完整 payload 编译进 JS 产物
190
+
191
+ 示例:
192
+
193
+ ```ts
194
+ buildVersionPlugin({
195
+ defineName: '__APP_VERSION__'
196
+ })
197
+ ```
198
+
199
+ 业务代码可直接读取:
200
+
201
+ ```ts
202
+ console.log(__APP_VERSION__)
203
+ ```
204
+
205
+ 打包后会在编译阶段被替换成字面量对象,因此适合给 Vue、TS、JS 模块直接消费。
206
+
207
+ 默认情况下会注入 `__VERSION__`。如果你不需要编译期常量,可显式传 `defineName: false` 关闭。
208
+
209
+ 如果同时开启 `defineName` 和 `globalName`,两者会共用同一份 payload:
210
+
211
+ - `defineName` 写入编译后的 JS
212
+ - `globalName` 注入运行时 HTML
213
+ - `version.json` 仍照常输出
214
+
181
215
  ### `injectToHtml`
182
216
 
183
217
  - 类型:`boolean`
@@ -387,6 +421,23 @@ pnpm build:fixture
387
421
  pnpm build:vitepress
388
422
  ```
389
423
 
424
+ 完整检查打包流程:
425
+
426
+ ```bash
427
+ pnpm build
428
+ pnpm build:fixture
429
+ pnpm build:vitepress
430
+ npm pack --dry-run
431
+ ```
432
+
433
+ 建议检查:
434
+
435
+ - `debug/fixture-app/dist/version.json` 包含 `time`、`env`、`pkgName`、`pkgVersion`
436
+ - `debug/fixture-app/dist/index.html` 只注入一次 `window["__VERSION__"]`
437
+ - `debug/vitepress-app/.vitepress/dist/meta/version.json` 包含 `fixture`、`time`、`env`
438
+ - VitePress 每个 HTML 只注入一次 `window["__VERSION__"]`
439
+ - VitePress build 日志只输出一次插件 payload
440
+
390
441
  ## 发布
391
442
 
392
443
  ```bash
@@ -406,6 +457,7 @@ npm publish --access public
406
457
  - `version.json` 输出正常
407
458
  - 普通 Vite HTML 注入正常
408
459
  - VitePress `transformHtml` 接入后注入正常
460
+ - VitePress build 没有重复输出插件 payload 日志
409
461
 
410
462
  查看最终发包内容:
411
463
 
@@ -502,6 +554,8 @@ export default defineConfig({
502
554
 
503
555
  Use the same `buildVersion` instance in both places. Calling `buildVersionPlugin()` twice creates two isolated instances, and the VitePress `transformHtml` helper will not receive the payload created during the Vite plugin lifecycle.
504
556
 
557
+ VitePress build includes a client bundle and an SSR bundle. The plugin emits `version.json` only from the final static bundle, so one VitePress build does not print duplicate payload logs or emit the same asset twice.
558
+
505
559
  ## Default Behavior
506
560
 
507
561
  With default options, the plugin:
@@ -809,6 +863,23 @@ pnpm build:fixture
809
863
  pnpm build:vitepress
810
864
  ```
811
865
 
866
+ Full local package check:
867
+
868
+ ```bash
869
+ pnpm build
870
+ pnpm build:fixture
871
+ pnpm build:vitepress
872
+ npm pack --dry-run
873
+ ```
874
+
875
+ Check:
876
+
877
+ - `debug/fixture-app/dist/version.json` contains `time`, `env`, `pkgName`, and `pkgVersion`
878
+ - `debug/fixture-app/dist/index.html` injects `window["__VERSION__"]` once
879
+ - `debug/vitepress-app/.vitepress/dist/meta/version.json` contains `fixture`, `time`, and `env`
880
+ - each VitePress HTML file injects `window["__VERSION__"]` once
881
+ - VitePress build prints the plugin payload log once
882
+
812
883
  ## Publishing
813
884
 
814
885
  ```bash
@@ -828,6 +899,7 @@ Before publishing, check:
828
899
  - `version.json` output
829
900
  - normal Vite HTML injection
830
901
  - VitePress `transformHtml` injection
902
+ - no duplicate plugin payload logs during VitePress build
831
903
 
832
904
  Inspect the publish package:
833
905
 
package/dist/index.cjs CHANGED
@@ -29,6 +29,7 @@ var import_node_path = require("path");
29
29
  var PLUGIN_NAME = "vite-plugin-build-version-file";
30
30
  var DEFAULT_FILENAME = "version.json";
31
31
  var DEFAULT_GLOBAL_NAME = "__VERSION__";
32
+ var DEFAULT_DEFINE_NAME = "__VERSION__";
32
33
  var DEFAULT_TIME_ZONE = "Asia/Shanghai";
33
34
  function createDefaultVersion(command, timeZone) {
34
35
  if (command === "serve") {
@@ -70,6 +71,15 @@ function normalizeGlobalName(globalName) {
70
71
  }
71
72
  return globalName;
72
73
  }
74
+ function normalizeDefineName(defineName) {
75
+ if (defineName === false || defineName === void 0) {
76
+ return defineName ?? false;
77
+ }
78
+ if (!defineName.trim()) {
79
+ throw new Error(`[${PLUGIN_NAME}] "defineName" cannot be empty.`);
80
+ }
81
+ return defineName;
82
+ }
73
83
  function normalizeTimeZone(timeZone) {
74
84
  const normalized = timeZone.trim();
75
85
  if (!normalized) {
@@ -154,6 +164,9 @@ function toRequestPath(base, fileName) {
154
164
  const baseWithoutTrailingSlash = withLeadingSlash.endsWith("/") ? withLeadingSlash.slice(0, -1) : withLeadingSlash;
155
165
  return `${baseWithoutTrailingSlash}/${fileName}`.replace(/\/{2,}/g, "/");
156
166
  }
167
+ function resolveProjectRoot(root) {
168
+ return root ? (0, import_node_path.resolve)(process.cwd(), root) : process.cwd();
169
+ }
157
170
  function resolveVersion(options, context, timeZone) {
158
171
  if (typeof options.version === "function") {
159
172
  return options.version(context);
@@ -180,10 +193,14 @@ function buildVersionPlugin(options = {}) {
180
193
  const globalName = normalizeGlobalName(
181
194
  options.globalName ?? DEFAULT_GLOBAL_NAME
182
195
  );
196
+ const defineName = normalizeDefineName(
197
+ options.defineName ?? DEFAULT_DEFINE_NAME
198
+ );
183
199
  const injectToHtml = options.injectToHtml ?? true;
184
200
  const timeZone = normalizeTimeZone(options.timeZone ?? DEFAULT_TIME_ZONE);
185
201
  const data = normalizeData(options.data);
186
202
  let payload;
203
+ let skipBundleEmit = false;
187
204
  const transformHtml = (code, ..._args) => {
188
205
  if (!injectToHtml || !payload) {
189
206
  return void 0;
@@ -192,7 +209,26 @@ function buildVersionPlugin(options = {}) {
192
209
  };
193
210
  const plugin = {
194
211
  name: PLUGIN_NAME,
212
+ config(userConfig, env) {
213
+ if (!payload) {
214
+ const context = {
215
+ command: env.command,
216
+ mode: env.mode
217
+ };
218
+ const packageInfo = readPackageInfo(resolveProjectRoot(userConfig.root));
219
+ payload = createPayload(options, context, data, timeZone, packageInfo);
220
+ }
221
+ if (!defineName || !payload) {
222
+ return void 0;
223
+ }
224
+ return {
225
+ define: {
226
+ [defineName]: JSON.stringify(payload)
227
+ }
228
+ };
229
+ },
195
230
  configResolved(config) {
231
+ skipBundleEmit = Boolean(config.build.ssr) && !config.build.ssrEmitAssets;
196
232
  if (payload) {
197
233
  return;
198
234
  }
@@ -235,7 +271,7 @@ function buildVersionPlugin(options = {}) {
235
271
  return tags;
236
272
  },
237
273
  generateBundle() {
238
- if (!payload) {
274
+ if (!payload || skipBundleEmit) {
239
275
  return;
240
276
  }
241
277
  this.emitFile({
package/dist/index.d.cts CHANGED
@@ -12,6 +12,7 @@ interface BuildVersionPayload {
12
12
  interface BuildVersionPluginOptions {
13
13
  filename?: string;
14
14
  globalName?: string;
15
+ defineName?: string | false;
15
16
  injectToHtml?: boolean;
16
17
  timeZone?: string;
17
18
  version?: string | number | ((ctx: BuildVersionContext) => string | number);
package/dist/index.d.ts CHANGED
@@ -12,6 +12,7 @@ interface BuildVersionPayload {
12
12
  interface BuildVersionPluginOptions {
13
13
  filename?: string;
14
14
  globalName?: string;
15
+ defineName?: string | false;
15
16
  injectToHtml?: boolean;
16
17
  timeZone?: string;
17
18
  version?: string | number | ((ctx: BuildVersionContext) => string | number);
package/dist/index.mjs CHANGED
@@ -1,9 +1,10 @@
1
1
  // src/index.ts
2
2
  import { existsSync, readFileSync } from "fs";
3
- import { dirname, join } from "path";
3
+ import { dirname, join, resolve } from "path";
4
4
  var PLUGIN_NAME = "vite-plugin-build-version-file";
5
5
  var DEFAULT_FILENAME = "version.json";
6
6
  var DEFAULT_GLOBAL_NAME = "__VERSION__";
7
+ var DEFAULT_DEFINE_NAME = "__VERSION__";
7
8
  var DEFAULT_TIME_ZONE = "Asia/Shanghai";
8
9
  function createDefaultVersion(command, timeZone) {
9
10
  if (command === "serve") {
@@ -45,6 +46,15 @@ function normalizeGlobalName(globalName) {
45
46
  }
46
47
  return globalName;
47
48
  }
49
+ function normalizeDefineName(defineName) {
50
+ if (defineName === false || defineName === void 0) {
51
+ return defineName ?? false;
52
+ }
53
+ if (!defineName.trim()) {
54
+ throw new Error(`[${PLUGIN_NAME}] "defineName" cannot be empty.`);
55
+ }
56
+ return defineName;
57
+ }
48
58
  function normalizeTimeZone(timeZone) {
49
59
  const normalized = timeZone.trim();
50
60
  if (!normalized) {
@@ -129,6 +139,9 @@ function toRequestPath(base, fileName) {
129
139
  const baseWithoutTrailingSlash = withLeadingSlash.endsWith("/") ? withLeadingSlash.slice(0, -1) : withLeadingSlash;
130
140
  return `${baseWithoutTrailingSlash}/${fileName}`.replace(/\/{2,}/g, "/");
131
141
  }
142
+ function resolveProjectRoot(root) {
143
+ return root ? resolve(process.cwd(), root) : process.cwd();
144
+ }
132
145
  function resolveVersion(options, context, timeZone) {
133
146
  if (typeof options.version === "function") {
134
147
  return options.version(context);
@@ -155,10 +168,14 @@ function buildVersionPlugin(options = {}) {
155
168
  const globalName = normalizeGlobalName(
156
169
  options.globalName ?? DEFAULT_GLOBAL_NAME
157
170
  );
171
+ const defineName = normalizeDefineName(
172
+ options.defineName ?? DEFAULT_DEFINE_NAME
173
+ );
158
174
  const injectToHtml = options.injectToHtml ?? true;
159
175
  const timeZone = normalizeTimeZone(options.timeZone ?? DEFAULT_TIME_ZONE);
160
176
  const data = normalizeData(options.data);
161
177
  let payload;
178
+ let skipBundleEmit = false;
162
179
  const transformHtml = (code, ..._args) => {
163
180
  if (!injectToHtml || !payload) {
164
181
  return void 0;
@@ -167,7 +184,26 @@ function buildVersionPlugin(options = {}) {
167
184
  };
168
185
  const plugin = {
169
186
  name: PLUGIN_NAME,
187
+ config(userConfig, env) {
188
+ if (!payload) {
189
+ const context = {
190
+ command: env.command,
191
+ mode: env.mode
192
+ };
193
+ const packageInfo = readPackageInfo(resolveProjectRoot(userConfig.root));
194
+ payload = createPayload(options, context, data, timeZone, packageInfo);
195
+ }
196
+ if (!defineName || !payload) {
197
+ return void 0;
198
+ }
199
+ return {
200
+ define: {
201
+ [defineName]: JSON.stringify(payload)
202
+ }
203
+ };
204
+ },
170
205
  configResolved(config) {
206
+ skipBundleEmit = Boolean(config.build.ssr) && !config.build.ssrEmitAssets;
171
207
  if (payload) {
172
208
  return;
173
209
  }
@@ -210,7 +246,7 @@ function buildVersionPlugin(options = {}) {
210
246
  return tags;
211
247
  },
212
248
  generateBundle() {
213
- if (!payload) {
249
+ if (!payload || skipBundleEmit) {
214
250
  return;
215
251
  }
216
252
  this.emitFile({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-build-version-file",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "A Vite plugin that emits version.json and injects version metadata into HTML.",
5
5
  "license": "MIT",
6
6
  "type": "module",