diff --git a/README.md b/README.md
index be7da74..e60ed53 100644
--- a/README.md
+++ b/README.md
@@ -98,6 +98,7 @@ Then you can use `vite-plugin-version-mark` ! 🎉
| ifGlobal | set a variable named *\`\_\_${APPNAME}\_VERSION\_\_\`* in the window
[For TypeScript users, make sure to add the type declarations in the env.d.ts or vite-env.d.ts file to get type checks and Intellisense.](https://vitejs.dev/config/shared-options.html#define) | `boolean` | true | `0.0.4+` |
| ifMeta | add \ in the \
| `boolean` | true | `0.0.1+` |
| ifExport | export the version field in the entry file. This may be used when you use vite to build a `library mode`.
Through `import { {APPNAME}_VERSION } from ` | `boolean` | false | `0.0.11+` |
+| outputFile | The build generates a static file based on the version, as described in the `outputFile` configuration below. | `boolean`/`function` | false | `0.1.1+` |
> The **version field** takes precedence: `command` > `ifShortSHA` > `ifGitSHA` > `version`
@@ -142,6 +143,24 @@ git branch -r --contains
View [CHANGELOG](./CHANGELOG.md)
+### outputFile Configuration Option
+
+If you want to enable it, you can set it to true, and it will create a file with the path “.well-known/version” and the content of the current version number in the relative build directory (dist for vite and .output/public for nuxt3).
+
+Alternatively, it can be set to a function that takes the version number as a parameter and returns an object. This allows you to define the content information generated, for example:
+
+```ts
+// vite.config.ts
+vitePluginVersionMark({
+ // ...other options
+ outputFile: (version) => ({
+ path: 'custom/version.json',
+ content: `{"version":"${version}"}`,
+ })
+}),
+```
+
+With this configuration, a file named "custom/version.json" will be generated, and its content will be {"version":"${current version number}"}.
## Star History
diff --git a/README_ZH.md b/README_ZH.md
index 1823a69..c793244 100644
--- a/README_ZH.md
+++ b/README_ZH.md
@@ -58,6 +58,7 @@ export default defineConfig({
ifMeta: true,
ifLog: true,
ifGlobal: true,
+ // outputFile: true,
})
],
})
@@ -77,6 +78,7 @@ export default defineNuxtConfig({
ifMeta: true,
ifLog: true,
ifGlobal: true,
+ // outputFile: true,
}]
],
})
@@ -99,7 +101,7 @@ export default defineNuxtConfig({
| ifGlobal | 在window上定义变量 *\`\_\_${APPNAME}\_VERSION\_\_\`*
[对于TypeScript使用者, 请确保您在 env.d.ts 或者 vite-env.d.ts 文件中定义该变量,以便通过类型检查。](https://vitejs.dev/config/shared-options.html#define) | `boolean` | true | `0.0.4+` |
| ifMeta | 在 `` 中添加 `` | `boolean` | true | `0.0.1+` |
| ifExport | 在入口文件导出版本字段。这在您使用vite构建 `library mode`时或许会用到。
通过 `import { {APPNAME}_VERSION} from ` | `boolean` | false | `0.0.11+` |
-
+| outputFile | 构建时根据版本生成一个静态文件,具体配置详见下方的 `outputFile` 配置项说明 | `boolean`/`function` | false | `0.1.1+` |
> **版本字段**的取值优先级为: `command` > `ifShortSHA` > `ifGitSHA` > `version`
@@ -143,6 +145,24 @@ git branch -r --contains
查看 [CHANGELOG](./CHANGELOG.md)
+### outputFile配置项说明
+
+如需启用可设置为true,会在相对构建目录(vite默认为dist,nuxt3默认为.output/public)下创建路径为“.well-known/version”的文件,内容为当前版本号。
+
+也可以设置为一个函数,该函数接收版本号作为参数,并返回一个对象,以便自行定义生成的内容信息,例如:
+
+```ts
+// vite.config.ts
+vitePluginVersionMark({
+ // ...other options
+ outputFile: (version) => ({
+ path: 'custom/version.json',
+ content: `{"version":"${version}"}`,
+ })
+}),
+```
+
+如此配置便可以生成一个名为“custom/version.json”的文件,内容为 `{"version":"${当前版本号}"}`。
## Star History
diff --git a/__tests__/fixtures/vite/index.html b/__tests__/fixtures/vite/index.html
index bcd9e06..59bfc5b 100644
--- a/__tests__/fixtures/vite/index.html
+++ b/__tests__/fixtures/vite/index.html
@@ -7,7 +7,6 @@
Vite + TS
-
-
+
diff --git a/__tests__/vite.test.ts b/__tests__/vite.test.ts
index 6305110..3b5dceb 100644
--- a/__tests__/vite.test.ts
+++ b/__tests__/vite.test.ts
@@ -1,7 +1,8 @@
import {resolve} from 'node:path'
+import {existsSync,readFileSync} from 'node:fs'
import {describe, test, expect} from 'vitest'
-import {build} from 'vite'
-import type {RollupOutput, OutputAsset, OutputChunk} from 'rollup'
+import {build, type InlineConfig} from 'vite'
+import type {RollupOutput} from 'rollup'
import {vitePluginVersionMark, type VitePluginVersionMarkInput} from '../src'
const entryPathForVite = './fixtures/vite'
@@ -9,7 +10,7 @@ const entryFilenameForVite = 'index.html'
const entryPathForLib = './fixtures/lib'
const entryFilenameForLib = 'index.js'
-async function buildVite(pluginConfig: VitePluginVersionMarkInput, entryPath, entryFilename, buildOptions = {}) {
+async function buildVite(pluginConfig: VitePluginVersionMarkInput, entryPath: string, entryFilename: string, buildOptions: InlineConfig = {}) {
const indexHtmlPath = resolve(__dirname, entryPath)
const outputs = (await build({
@@ -23,11 +24,19 @@ async function buildVite(pluginConfig: VitePluginVersionMarkInput, entryPath, en
const output = Array.isArray(outputs) ? outputs[0].output : outputs.output
const file = output.find(
item => item.fileName === entryFilename,
- ) as OutputAsset | OutputChunk
-
- const codeStr = file.source || file.code
-
- return await codeStr.toString()
+ )
+ if (!file) {
+ throw new Error(`File with name ${entryFilename} not found in output.`)
+ }
+ let codeStr = ''
+ if ('source' in file) {
+ codeStr = file.source.toString()
+ } else if ('code' in file) {
+ codeStr = file.code
+ } else {
+ throw new Error('The file object lacks both `source` and `code` properties.')
+ }
+ return codeStr
}
// https://github.com/Applelo/unplugin-inject-preload/blob/main/test/vite.test.ts#L24
@@ -135,8 +144,80 @@ describe('VitePlugin', () => {
)
expect(output).toMatchSnapshot()
})
+
+ test('output: File(true)', async () => {
+ const outDir = resolve(__dirname, entryPathForVite, 'dist')
+ await buildVite(
+ {
+ version: '1.0.0',
+ outputFile: true,
+ ifMeta: false,
+ ifLog: false,
+ ifGlobal: false,
+ ifExport: false,
+ },
+ entryPathForLib,
+ entryFilenameForLib,
+ {
+ build: {
+ lib: {
+ entry: './index.ts',
+ name: 'index',
+ fileName: 'index',
+ formats: ['es'],
+ },
+ outDir,
+ },
+ },
+ )
+ const defaultFilePath = resolve(outDir, '.well-known/version')
+ // File should be created
+ expect(existsSync(defaultFilePath)).toBe(true)
+ // File should contain version
+ expect(readFileSync(defaultFilePath, 'utf-8')).toEqual('1.0.0')
+ })
+
+ test('output: File(custom function)', async () => {
+ const outDir = resolve(__dirname, entryPathForVite, 'dist')
+ const customPath = 'custom/version.json'
+ await buildVite(
+ {
+ version: '1.0.0',
+ outputFile(version){
+ return {
+ path: customPath,
+ content: `{"version":"${version}"}`,
+ }
+ },
+ ifMeta: false,
+ ifLog: false,
+ ifGlobal: false,
+ ifExport: false,
+ },
+ entryPathForLib,
+ entryFilenameForLib,
+ {
+ build: {
+ lib: {
+ entry: './index.ts',
+ name: 'index',
+ fileName: 'index',
+ formats: ['es'],
+ },
+ outDir,
+ },
+ },
+ )
+ const customFilePath = resolve(outDir, customPath)
+ // custom file should be created
+ expect(existsSync(customFilePath)).toBe(true)
+ // custom file should contain version with json format
+ expect(readFileSync(customFilePath, 'utf-8')).toEqual(JSON.stringify({'version': '1.0.0'}))
+ })
})
+
+
// describe('longSHA', () => { })
// describe('shortSHA', () => { })
// describe('command', () => { })
diff --git a/playground/nuxt3-webapp/nuxt.config.ts b/playground/nuxt3-webapp/nuxt.config.ts
index b816ac3..4cad2fb 100644
--- a/playground/nuxt3-webapp/nuxt.config.ts
+++ b/playground/nuxt3-webapp/nuxt.config.ts
@@ -10,6 +10,7 @@ export default defineNuxtConfig({
ifMeta: true,
ifLog: true,
ifGlobal: true,
+ outputFile: true,
}],
],
})
diff --git a/playground/vite-lib/vite.config.ts b/playground/vite-lib/vite.config.ts
index e8b0f33..c0c3ffd 100644
--- a/playground/vite-lib/vite.config.ts
+++ b/playground/vite-lib/vite.config.ts
@@ -1,4 +1,4 @@
-import {defineConfig} from 'vite'
+import {defineConfig, type Plugin} from 'vite'
import {vitePluginVersionMark} from '../../src/plugins/vite'
export default defineConfig({
@@ -17,6 +17,7 @@ export default defineConfig({
ifLog: true,
ifGlobal: true,
ifExport: true,
- }),
+ outputFile: true,
+ }) as Plugin,
],
})
diff --git a/src/plugins/core/index.ts b/src/plugins/core/index.ts
index 0730cc9..cf67436 100644
--- a/src/plugins/core/index.ts
+++ b/src/plugins/core/index.ts
@@ -17,8 +17,19 @@ interface VitePluginVersionMarkCommandInput extends VitePluginVersionMarkBaseInp
command?: string
}
-export type VitePluginVersionMarkInput = VitePluginVersionMarkGitInput & VitePluginVersionMarkCommandInput
+interface OutputFile {
+ path: string;
+ content: string
+}
+type OutputFileFunction = (version: string) => OutputFile | OutputFile[]
+interface VitePluginVersionMarkFileInput extends VitePluginVersionMarkBaseInput {
+ outputFile?: boolean | OutputFileFunction
+}
+
+export type VitePluginVersionMarkInput = VitePluginVersionMarkGitInput & VitePluginVersionMarkCommandInput & VitePluginVersionMarkFileInput
+
export type VitePluginVersionMarkConfig = {
+ fileList: { path: string, content: string }[]
ifMeta: boolean
ifLog: boolean
ifGlobal: boolean
@@ -54,17 +65,31 @@ export const analyticOptions: (options: VitePluginVersionMarkInput) => Promise {
+ switch (typeof outputFile) {
+ case 'function': {
+ const res = outputFile(printVersion)
+ return Array.isArray(res) ? res : [res]
+ }
+ case 'boolean':
+ return outputFile ? [{path: '.well-known/version', content: printVersion}] : []
+ default:
+ return []
+ }
+ })()
return {
ifMeta,
ifLog,
ifGlobal,
ifExport,
+ fileList,
printVersion,
printName,
printInfo,
diff --git a/src/plugins/nuxt3.ts b/src/plugins/nuxt3.ts
index 5e79865..659567a 100644
--- a/src/plugins/nuxt3.ts
+++ b/src/plugins/nuxt3.ts
@@ -1,4 +1,6 @@
// https://github.com/nuxt-modules/google-adsense/blob/master/src/module.ts
+import {mkdir, writeFile} from 'node:fs/promises'
+import {resolve,dirname} from 'node:path'
import {defineNuxtModule} from '@nuxt/kit'
import type {NuxtModule} from '@nuxt/schema'
import {VitePluginVersionMarkInput, analyticOptions} from './core'
@@ -12,6 +14,7 @@ const nuxt3Module: NuxtModule = defineNuxtModule({
// https://github.com/nuxt/bridge/blob/main/packages/bridge/src/module.ts
async setup(options, nuxt) {
const {
+ fileList,
ifMeta,
ifLog,
ifGlobal,
@@ -41,6 +44,23 @@ const nuxt3Module: NuxtModule = defineNuxtModule({
children: `__${printName}__ = "${printVersion}"`,
})
}
+ if (fileList.length > 0) {
+ nuxt.hook('nitro:build:public-assets', async ({options: {output: {publicDir}}}) => {
+ await Promise.all(fileList.map(async ({path, content = ''}) => {
+ const dir = dirname(path)
+ const fullDir = resolve(publicDir, dir)
+ const outputFilePath = resolve(publicDir, path)
+ try {
+ await mkdir(fullDir, {recursive: true})
+ await writeFile(outputFilePath, content)
+ console.info(`Generated version file in ${outputFilePath}`)
+ } catch (error) {
+ console.error(`Failed to generate file at ${outputFilePath}:`, error)
+ throw error
+ }
+ }))
+ })
+ }
},
})
diff --git a/src/plugins/vite.ts b/src/plugins/vite.ts
index 53a1fd9..75d1279 100644
--- a/src/plugins/vite.ts
+++ b/src/plugins/vite.ts
@@ -1,3 +1,5 @@
+import {mkdir, writeFile} from 'node:fs/promises'
+import {resolve,dirname} from 'node:path'
import {analyticOptions} from './core'
import type {VitePluginVersionMarkInput, VitePluginVersionMarkConfig} from './core'
import type {Plugin, IndexHtmlTransformResult} from 'vite'
@@ -9,11 +11,12 @@ export const vitePluginVersionMark: (options?: VitePluginVersionMarkInput) => Pl
if (!versionMarkConfig) versionMarkConfig = await analyticOptions(options)
return versionMarkConfig
}
+ let outDir: string
return {
name: 'vite-plugin-version-mark',
- async config () {
+ async config() {
const {
ifGlobal,
printName,
@@ -21,7 +24,7 @@ export const vitePluginVersionMark: (options?: VitePluginVersionMarkInput) => Pl
} = await getVersionMarkConfig()
if (ifGlobal) {
- const keyName = `__${printName}__`
+ const keyName = `__${printName}__`
return {
define: {
[keyName]: JSON.stringify(printVersion),
@@ -37,7 +40,7 @@ export const vitePluginVersionMark: (options?: VitePluginVersionMarkInput) => Pl
printName,
printVersion,
} = await getVersionMarkConfig()
-
+
let modifiedCode = code
if (ifExport) modifiedCode += `\nexport const ${printName} = '${printVersion}';`
@@ -45,7 +48,7 @@ export const vitePluginVersionMark: (options?: VitePluginVersionMarkInput) => Pl
code: modifiedCode,
map: null,
}
- }
+ }
},
async transformIndexHtml() {
@@ -86,5 +89,23 @@ export const vitePluginVersionMark: (options?: VitePluginVersionMarkInput) => Pl
return els
},
- }
+ configResolved(config) {
+ outDir = config.build.outDir
+ },
+ async closeBundle() {
+ const {fileList} = await getVersionMarkConfig()
+ if (!fileList.length) return
+ await Promise.all(fileList.map(async ({path, content = ''}) => {
+ try {
+ const dir = dirname(path)
+ await mkdir(resolve(outDir, dir), {recursive: true})
+ const outputFilePath = resolve(outDir, path)
+ await writeFile(outputFilePath, content)
+ this.info(`Generate version file in ${outputFilePath}`)
+ } catch (error) {
+ this.error(`Failed to generate version file at ${path}: ${(error as Error).message}`)
+ }
+ }))
+ },
+ } as Plugin
}