@quiteer/vite 0.0.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 +160 -0
- package/cli.ts +62 -0
- package/dist/bin/context-Db5EuGKU-B3vpL0eS.mjs +24 -0
- package/dist/bin/dist-BmyFpZwL.mjs +7 -0
- package/dist/bin/dist-BniM_x9D.mjs +5256 -0
- package/dist/bin/dist-Bvgk2hb8.mjs +187 -0
- package/dist/bin/dist-CjNY_432.mjs +473 -0
- package/dist/bin/dist-DQNZhGEj.mjs +10562 -0
- package/dist/bin/esm-CQYKr9An.mjs +1557 -0
- package/dist/bin/experimental-index-DiVJ_oZg.mjs +71 -0
- package/dist/bin/qvite.mjs +244 -0
- package/dist/bin/resolver-DymnxKPB-UI_9xIg2.mjs +16 -0
- package/dist/bin/src-BwxUhqZU-Dr1MNcyS.mjs +5046 -0
- package/dist/bin/tsc-TmK__neM.mjs +406 -0
- package/dist/index.d.mts +118 -0
- package/dist/index.mjs +5965 -0
- package/index.ts +106 -0
- package/package.json +60 -0
- package/src/build.ts +43 -0
- package/src/defaults.ts +36 -0
- package/src/getConfig.ts +52 -0
- package/src/plugins.ts +14 -0
- package/src/store.ts +13 -0
- package/src/transform.ts +50 -0
- package/src/typings.ts +48 -0
- package/src/watch.ts +60 -0
- package/tsconfig.json +24 -0
- package/tsdown.config.ts +20 -0
package/index.ts
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { UserConfig as TsdownUserConfig } from 'tsdown'
|
|
2
|
+
import type { UserConfig as ViteUserConfig } from 'vite'
|
|
3
|
+
import type { QviteConfig, QviteConfigExport, QviteConfigFnObject } from './src/typings'
|
|
4
|
+
import { defineConfig as tsdownDefineConfig } from 'tsdown'
|
|
5
|
+
import { defineConfig as viteDefineConfig } from 'vite'
|
|
6
|
+
|
|
7
|
+
export type * from './src/typings'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* `@quiteer/vite` 配置声明函数(类型辅助)
|
|
11
|
+
*
|
|
12
|
+
* 为 `qvite.config.ts` 提供强类型提示,支持对象、Promise 与函数多种导出形式
|
|
13
|
+
*
|
|
14
|
+
* @param config - 可为对象、Promise 或按环境返回配置的函数
|
|
15
|
+
* @returns 与入参同构的配置对象/函数,用于类型推断,无运行时副作用
|
|
16
|
+
* @throws {TypeError} 不抛出异常(纯类型辅助),运行时直接返回
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { defineConfig } from 'qvite'
|
|
21
|
+
* export default defineConfig({ mode: 'development', vite: { plugins: [] } })
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @remarks
|
|
25
|
+
* - 函数重载覆盖对象、Promise、函数等场景
|
|
26
|
+
* - 仅用于 TS 类型推断,运行时原样返回
|
|
27
|
+
*
|
|
28
|
+
* @security
|
|
29
|
+
* 不读取文件、不处理敏感信息
|
|
30
|
+
*
|
|
31
|
+
* @performance
|
|
32
|
+
* 常量时间返回,无额外开销
|
|
33
|
+
*/
|
|
34
|
+
export function defineConfig(config: QviteConfig): QviteConfig
|
|
35
|
+
|
|
36
|
+
export function defineConfig(config: Promise<QviteConfig>): Promise<QviteConfig>
|
|
37
|
+
|
|
38
|
+
export function defineConfig(config: QviteConfigFnObject): QviteConfigFnObject
|
|
39
|
+
|
|
40
|
+
export function defineConfig(config: QviteConfigExport): QviteConfigExport
|
|
41
|
+
|
|
42
|
+
export function defineConfig(config: QviteConfigExport): QviteConfigExport {
|
|
43
|
+
return config
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// 类型导出通过 dts 文件与 typesVersions 提供,避免在 JS 解析阶段出现命名导出未定义的问题
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 暴露 Vite 的 `defineConfig`(类型辅助包装)
|
|
50
|
+
*
|
|
51
|
+
* 为 Vite 配置文件提供强类型提示;内部委托给 `vite.defineConfig`
|
|
52
|
+
*
|
|
53
|
+
* @param config - Vite 配置对象或按环境返回配置的函数
|
|
54
|
+
* @returns 与入参同构的配置对象/函数,用于类型推断
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* import { defineViteConfig } from 'qvite'
|
|
59
|
+
* export default defineViteConfig({ plugins: [] })
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* @remarks
|
|
63
|
+
* - 纯类型辅助,运行时直接委托给 Vite 的 `defineConfig`
|
|
64
|
+
*
|
|
65
|
+
* @security
|
|
66
|
+
* 无敏感信息处理
|
|
67
|
+
*
|
|
68
|
+
* @performance
|
|
69
|
+
* 常量时间委托,无额外开销
|
|
70
|
+
*/
|
|
71
|
+
export function defineViteConfig(
|
|
72
|
+
config: Parameters<typeof viteDefineConfig>[0]
|
|
73
|
+
): ReturnType<typeof viteDefineConfig> {
|
|
74
|
+
return viteDefineConfig(config as ViteUserConfig)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* 暴露 tsdown 的 `defineConfig`(类型辅助包装)
|
|
79
|
+
*
|
|
80
|
+
* 为 tsdown 配置文件提供强类型提示;内部委托给 `tsdown.defineConfig`
|
|
81
|
+
*
|
|
82
|
+
* @param config - tsdown 配置对象或配置数组
|
|
83
|
+
* @returns 与入参同构的配置对象/数组,用于类型推断
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* import { defineTsdownConfig } from 'qvite'
|
|
88
|
+
* export default defineTsdownConfig([
|
|
89
|
+
* { name: 'client', entry: ['src/index.ts'], outDir: 'dist/client', platform: 'node' }
|
|
90
|
+
* ])
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* @remarks
|
|
94
|
+
* - 纯类型辅助,运行时直接委托给 tsdown 的 `defineConfig`
|
|
95
|
+
*
|
|
96
|
+
* @security
|
|
97
|
+
* 无敏感信息处理
|
|
98
|
+
*
|
|
99
|
+
* @performance
|
|
100
|
+
* 常量时间委托,无额外开销
|
|
101
|
+
*/
|
|
102
|
+
export function defineTsdownConfig(
|
|
103
|
+
config: Parameters<typeof tsdownDefineConfig>[0]
|
|
104
|
+
): ReturnType<typeof tsdownDefineConfig> {
|
|
105
|
+
return tsdownDefineConfig(config as TsdownUserConfig | TsdownUserConfig[])
|
|
106
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@quiteer/vite",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"packageManager": "pnpm@10.20.0",
|
|
6
|
+
"description": "在 vite 的基础上增强的前端架构 cli",
|
|
7
|
+
"author": "quiteer",
|
|
8
|
+
"license": "ISC",
|
|
9
|
+
"homepage": "https://quiteerjs.github.io/web/ci/qvite.html",
|
|
10
|
+
"keywords": [
|
|
11
|
+
"vite",
|
|
12
|
+
"cli"
|
|
13
|
+
],
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.mts",
|
|
17
|
+
"import": "./dist/index.mjs",
|
|
18
|
+
"require": "./dist/index.mjs"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"main": "./dist/index.mjs",
|
|
22
|
+
"module": "./dist/index.mjs",
|
|
23
|
+
"types": "./dist/index.d.mts",
|
|
24
|
+
"typesVersions": {
|
|
25
|
+
"*": {
|
|
26
|
+
"*": [
|
|
27
|
+
"./src/*"
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"bin": {
|
|
32
|
+
"qvite": "./dist/bin/qvite.mjs"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"dev": "tsdown -w",
|
|
36
|
+
"build": "tsdown",
|
|
37
|
+
"release": "qui r --tag-prefix qvite && qui gc && tsdown && pnpm publish"
|
|
38
|
+
},
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public",
|
|
41
|
+
"registry": "https://registry.npmjs.org/"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@quiteer/is": "workspace:*",
|
|
45
|
+
"@quiteer/parser-config": "^1.0.3",
|
|
46
|
+
"@quiteer/scripts": "workspace:*",
|
|
47
|
+
"@quiteer/utils": "workspace:*",
|
|
48
|
+
"@quiteer/vite-plugins": "workspace:^",
|
|
49
|
+
"@types/fs-extra": "^11.0.4",
|
|
50
|
+
"@types/node": "^24.10.1",
|
|
51
|
+
"c12": "3.3.2",
|
|
52
|
+
"cac": "6.7.14",
|
|
53
|
+
"fs-extra": "^11.3.2",
|
|
54
|
+
"kolorist": "1.8.0",
|
|
55
|
+
"portfinder": "^1.0.38",
|
|
56
|
+
"semver": "^7.6.3",
|
|
57
|
+
"vite": "npm:rolldown-vite@7.2.2",
|
|
58
|
+
"zx": "^8.8.5"
|
|
59
|
+
}
|
|
60
|
+
}
|
package/src/build.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { QviteConfig } from './typings'
|
|
2
|
+
import { build as viteBuild } from 'vite'
|
|
3
|
+
|
|
4
|
+
import { normalizeConfig, toViteInlineConfig } from './transform'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 执行构建流程(生产模式)
|
|
8
|
+
*
|
|
9
|
+
* 先构建 tsdown 产物(若配置提供),再调用 Vite 的 `build` 完成前端打包
|
|
10
|
+
*
|
|
11
|
+
* @param options - Qvite 配置对象,含 `vite` 与 `tsdown` 等子配置
|
|
12
|
+
* @returns Promise<void> 构建完成无返回值
|
|
13
|
+
* @throws {Error} 当 Vite 或 tsdown 构建失败时抛出异常
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* await build({ mode: 'production', minify: true, vite: { build: { outDir: 'dist' } } })
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @remarks
|
|
21
|
+
* - `minify` 会映射为 Vite 的 `build.minify`
|
|
22
|
+
* - 若 `tsdown` 配置存在,则会先执行 `tsdownBuild`
|
|
23
|
+
*
|
|
24
|
+
* @security
|
|
25
|
+
* 不写入敏感信息,仅调用编译器
|
|
26
|
+
*
|
|
27
|
+
* @performance
|
|
28
|
+
* 构建性能取决于 Vite/tsdown 自身实现
|
|
29
|
+
*/
|
|
30
|
+
export async function build(options: QviteConfig): Promise<void> {
|
|
31
|
+
const normalized = await normalizeConfig(options)
|
|
32
|
+
|
|
33
|
+
if (normalized.tsdown && (
|
|
34
|
+
(Array.isArray(normalized.tsdown) && normalized.tsdown.length > 0)
|
|
35
|
+
|| (!Array.isArray(normalized.tsdown) && Object.keys(normalized.tsdown).length > 0)
|
|
36
|
+
)) {
|
|
37
|
+
const { build: tsdownBuild } = await import('tsdown') as any
|
|
38
|
+
await tsdownBuild(normalized.tsdown as any)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const inline = await toViteInlineConfig(normalized)
|
|
42
|
+
await viteBuild(inline)
|
|
43
|
+
}
|
package/src/defaults.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { QviteConfig } from './typings'
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
|
|
4
|
+
export const defaultOptions = {
|
|
5
|
+
plugins: {
|
|
6
|
+
Vue: [{ customElement: true }],
|
|
7
|
+
UnoCSS: false,
|
|
8
|
+
VueDevTools: [{}],
|
|
9
|
+
VueJsx: [{}],
|
|
10
|
+
Progress: [{}],
|
|
11
|
+
FileChangeLogger: [{}],
|
|
12
|
+
RemoveConsole: [{}],
|
|
13
|
+
MockRouter: [{}]
|
|
14
|
+
},
|
|
15
|
+
html: {
|
|
16
|
+
|
|
17
|
+
},
|
|
18
|
+
env: {
|
|
19
|
+
obfuscate: false,
|
|
20
|
+
requiredKeys: ['desc']
|
|
21
|
+
},
|
|
22
|
+
vite: {
|
|
23
|
+
server: {
|
|
24
|
+
port: 3000,
|
|
25
|
+
strictPort: false
|
|
26
|
+
},
|
|
27
|
+
resolve: {
|
|
28
|
+
alias: {
|
|
29
|
+
'@': fileURLToPath(new URL('./src', import.meta.url))
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
build: {
|
|
33
|
+
minify: false
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
} satisfies QviteConfig
|
package/src/getConfig.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Command, Mode, QviteConfig, QviteConfigFn } from './typings'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import { isFunction } from '@quiteer/is'
|
|
4
|
+
import { parserConfig } from '@quiteer/parser-config'
|
|
5
|
+
import { deepMerge } from '@quiteer/utils'
|
|
6
|
+
import { pathExists } from 'fs-extra'
|
|
7
|
+
import { loadEnv } from 'vite'
|
|
8
|
+
import { store } from './store'
|
|
9
|
+
|
|
10
|
+
const NOT_FOUND = '找不到 qvite.config.ts | qvite.config.js | qvite.config.json , 请在根目录下添加配置文件 , 或显式的指定配置文件路径(相对于根目录)'
|
|
11
|
+
const PARSING_FAILED = '找到了配置文件,但解析配置文件失败!'
|
|
12
|
+
|
|
13
|
+
const root = store.get('root') as string
|
|
14
|
+
|
|
15
|
+
async function configPath(filePath: string) {
|
|
16
|
+
if (filePath)
|
|
17
|
+
return join(root, filePath)
|
|
18
|
+
|
|
19
|
+
const configList = ['ts', 'mjs', 'cjs', 'js'].map(suffix => `${join(root, 'qvite.config')}.${suffix}`)
|
|
20
|
+
|
|
21
|
+
const index = (await Promise.all(configList.map(path => pathExists(path)))).findIndex(flag => flag)
|
|
22
|
+
|
|
23
|
+
if (index > -1)
|
|
24
|
+
return configList[index]
|
|
25
|
+
|
|
26
|
+
throw new Error(NOT_FOUND)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function getConfig(filePath: string): Promise<QviteConfig> {
|
|
30
|
+
const path = await configPath(filePath)
|
|
31
|
+
|
|
32
|
+
const command = store.get<Command>('command')!
|
|
33
|
+
const mode = store.get<Mode>('mode')!
|
|
34
|
+
const modeEnv = loadEnv(mode, root, store.get<string[]>('prefixes')!)
|
|
35
|
+
const defaultEnv = loadEnv('', root, store.get<string[]>('prefixes')!)
|
|
36
|
+
|
|
37
|
+
const env = deepMerge({}, defaultEnv, modeEnv)
|
|
38
|
+
try {
|
|
39
|
+
const option: QviteConfig = await parserConfig(path, 'qvite.config')
|
|
40
|
+
|
|
41
|
+
if (isFunction(option)) {
|
|
42
|
+
const configFn = option as QviteConfigFn
|
|
43
|
+
return configFn({ command, mode, env, root })
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return option
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
console.error('error :>> ', error)
|
|
50
|
+
throw new Error(PARSING_FAILED)
|
|
51
|
+
}
|
|
52
|
+
}
|
package/src/plugins.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { PluginOption } from 'vite'
|
|
2
|
+
import type { QvitePlugins } from './typings'
|
|
3
|
+
import { fileChangeLoggerPlugin, mockRouterPlugin, Progress, removeConsolePlugin, UnoCSS, Vue, VueDevTools, VueJsx } from '@quiteer/vite-plugins'
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
FileChangeLogger: fileChangeLoggerPlugin,
|
|
7
|
+
MockRouter: mockRouterPlugin,
|
|
8
|
+
RemoveConsole: removeConsolePlugin,
|
|
9
|
+
Progress,
|
|
10
|
+
Vue,
|
|
11
|
+
VueDevTools,
|
|
12
|
+
VueJsx,
|
|
13
|
+
UnoCSS
|
|
14
|
+
} satisfies Record<keyof QvitePlugins, (...args: any[]) => PluginOption>
|
package/src/store.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { cwd } from 'node:process'
|
|
2
|
+
import { PersistentStore } from '@quiteer/utils'
|
|
3
|
+
|
|
4
|
+
export const store = PersistentStore.getInstance('qvite')
|
|
5
|
+
|
|
6
|
+
store.set('root', cwd())
|
|
7
|
+
store.set('command', 'serve')
|
|
8
|
+
store.set('config', 'qvite.config.ts')
|
|
9
|
+
store.set('mode', 'development')
|
|
10
|
+
store.set('env', {})
|
|
11
|
+
store.set('minify', false)
|
|
12
|
+
store.set('port', 8080)
|
|
13
|
+
store.set('prefixes', ['QVITE_', 'VITE_'])
|
package/src/transform.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { InlineConfig, Plugin } from 'vite'
|
|
2
|
+
import type { QviteConfig, QvitePlugins } from './typings'
|
|
3
|
+
import { deepMerge } from '@quiteer/utils'
|
|
4
|
+
import { envConfigPlugin, virtualHtmlPlugin } from '@quiteer/vite-plugins'
|
|
5
|
+
import { mergeConfig } from 'vite'
|
|
6
|
+
import { defaultOptions } from './defaults'
|
|
7
|
+
import defaultPlugins from './plugins'
|
|
8
|
+
import { store } from './store'
|
|
9
|
+
|
|
10
|
+
type NormalizeConfig = Required<QviteConfig>
|
|
11
|
+
|
|
12
|
+
export async function normalizeConfig(raw: QviteConfig): Promise<NormalizeConfig> {
|
|
13
|
+
const config = deepMerge<QviteConfig>(defaultOptions, raw) as NormalizeConfig
|
|
14
|
+
return config
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function geVitePlugins(config: NormalizeConfig) {
|
|
18
|
+
const { html, env, plugins } = config
|
|
19
|
+
|
|
20
|
+
const pluginKeys = Object.keys(plugins) as (keyof QvitePlugins)[]
|
|
21
|
+
|
|
22
|
+
const vitePlugins = pluginKeys.map((key) => {
|
|
23
|
+
const pluginOptions = plugins[key]
|
|
24
|
+
|
|
25
|
+
const pluginFn = defaultPlugins[key] as (...args: any[]) => Plugin
|
|
26
|
+
|
|
27
|
+
if (Array.isArray(pluginOptions)) {
|
|
28
|
+
return pluginFn(...pluginOptions as any[])
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return null
|
|
32
|
+
}).filter(Boolean) as Plugin[]
|
|
33
|
+
return [...vitePlugins, virtualHtmlPlugin(html), envConfigPlugin(env)]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function toViteInlineConfig(config: NormalizeConfig): Promise<InlineConfig> {
|
|
37
|
+
const mode = store.get<string>('mode')!
|
|
38
|
+
const root = store.get<string>('root')!
|
|
39
|
+
|
|
40
|
+
const plugins = geVitePlugins(config)
|
|
41
|
+
|
|
42
|
+
const inline: InlineConfig = mergeConfig({
|
|
43
|
+
configFile: false,
|
|
44
|
+
root,
|
|
45
|
+
mode,
|
|
46
|
+
plugins
|
|
47
|
+
}, { ...config.vite })
|
|
48
|
+
|
|
49
|
+
return inline
|
|
50
|
+
}
|
package/src/typings.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { EnvConfigPluginOptions, fileChangeLoggerPlugin, mockRouterPlugin, Progress, removeConsolePlugin, UnoCSS, VirtualHtmlOptions, Vue, VueDevTools, VueJsx } from '@quiteer/vite-plugins'
|
|
2
|
+
import type { UserConfig } from 'tsdown'
|
|
3
|
+
import type { UserConfig as ViteUserConfig } from 'vite'
|
|
4
|
+
|
|
5
|
+
export type { EnvConfig } from '@quiteer/vite-plugins'
|
|
6
|
+
|
|
7
|
+
export type PluginOptions<T extends (...args: any) => any> = boolean | Parameters<T>
|
|
8
|
+
|
|
9
|
+
export interface QvitePlugins {
|
|
10
|
+
Vue?: PluginOptions<typeof Vue>
|
|
11
|
+
UnoCSS?: PluginOptions<typeof UnoCSS>
|
|
12
|
+
VueJsx?: PluginOptions<typeof VueJsx>
|
|
13
|
+
Progress?: PluginOptions<typeof Progress>
|
|
14
|
+
VueDevTools?: PluginOptions<typeof VueDevTools>
|
|
15
|
+
RemoveConsole?: PluginOptions<typeof removeConsolePlugin>
|
|
16
|
+
MockRouter?: PluginOptions<typeof mockRouterPlugin>
|
|
17
|
+
FileChangeLogger?: PluginOptions<typeof fileChangeLoggerPlugin>
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface QviteConfig {
|
|
21
|
+
vite?: ViteUserConfig
|
|
22
|
+
tsdown?: UserConfig | UserConfig[]
|
|
23
|
+
plugins?: QvitePlugins
|
|
24
|
+
html?: VirtualHtmlOptions
|
|
25
|
+
env?: EnvConfigPluginOptions
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type Mode = 'development' | 'production' | 'test' | 'staging' | 'production' | string
|
|
29
|
+
|
|
30
|
+
export type Command = 'build' | 'serve'
|
|
31
|
+
|
|
32
|
+
export interface ConfigEnv<T = Record<string, string>> {
|
|
33
|
+
command: Command
|
|
34
|
+
mode: Mode
|
|
35
|
+
env: T
|
|
36
|
+
root: string
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type QviteConfigFnObject = (env: ConfigEnv) => QviteConfig
|
|
40
|
+
export type QviteConfigFnPromise = (env: ConfigEnv) => Promise<QviteConfig>
|
|
41
|
+
export type QviteConfigFn = (env: ConfigEnv) => QviteConfig | Promise<QviteConfig>
|
|
42
|
+
|
|
43
|
+
export type QviteConfigExport
|
|
44
|
+
= | QviteConfig
|
|
45
|
+
| Promise<QviteConfig>
|
|
46
|
+
| QviteConfigFnObject
|
|
47
|
+
| QviteConfigFnPromise
|
|
48
|
+
| QviteConfigFn
|
package/src/watch.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { QviteConfig } from './typings'
|
|
2
|
+
import { getPortPromise } from 'portfinder'
|
|
3
|
+
import { createServer } from 'vite'
|
|
4
|
+
import { store } from './store'
|
|
5
|
+
import { normalizeConfig, toViteInlineConfig } from './transform'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 启动开发服务器(热更新)
|
|
9
|
+
*
|
|
10
|
+
* 根据规范化配置启动 Vite Dev Server,自动选择可用端口,并打印访问地址
|
|
11
|
+
*
|
|
12
|
+
* @param options - Qvite 配置对象,包含 `vite` 与 `tsdown`
|
|
13
|
+
* @returns Promise<void>
|
|
14
|
+
* @throws {Error} 当端口查找或 Vite 启动失败时抛出异常
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* await watch({ port: 3000, vite: { plugins: [] } })
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @remarks
|
|
22
|
+
* - 若配置的 `port` 被占用,将自动选取下一个可用端口
|
|
23
|
+
* - 启动前执行一次 tsdown 构建,便于开发期产物可用
|
|
24
|
+
*
|
|
25
|
+
* @security
|
|
26
|
+
* 不暴露敏感信息,仅打印本地 URL
|
|
27
|
+
*
|
|
28
|
+
* @performance
|
|
29
|
+
* 端口探测为 O(1) 近似成本,服务性能由 Vite 决定
|
|
30
|
+
*/
|
|
31
|
+
export async function watch(options: QviteConfig): Promise<void> {
|
|
32
|
+
const normalized = await normalizeConfig(options)
|
|
33
|
+
const port = normalized.vite?.server?.port || store.get<number>('port')!
|
|
34
|
+
|
|
35
|
+
const p = await getPortPromise({
|
|
36
|
+
port
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
store.set('port', p)
|
|
40
|
+
|
|
41
|
+
const inline = await toViteInlineConfig(normalized)
|
|
42
|
+
|
|
43
|
+
const viteDevServer = await createServer({
|
|
44
|
+
...inline,
|
|
45
|
+
server: { ...inline.server, port: p }
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
await viteDevServer.listen(p)
|
|
49
|
+
viteDevServer.printUrls()
|
|
50
|
+
|
|
51
|
+
if (normalized.tsdown) {
|
|
52
|
+
const { build: tsdownBuild } = await import('tsdown')
|
|
53
|
+
if (!Array.isArray(normalized.tsdown)) {
|
|
54
|
+
await tsdownBuild(normalized.tsdown)
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
await Promise.all(normalized.tsdown.map(tsdownBuild))
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"jsx": "preserve",
|
|
5
|
+
"lib": ["DOM", "ESNext"],
|
|
6
|
+
"baseUrl": ".",
|
|
7
|
+
"module": "ESNext",
|
|
8
|
+
"moduleResolution": "bundler",
|
|
9
|
+
"paths": {
|
|
10
|
+
"@/*": ["./src/*"]
|
|
11
|
+
},
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"types": ["node"],
|
|
14
|
+
"strict": true,
|
|
15
|
+
"strictNullChecks": true,
|
|
16
|
+
"noUnusedLocals": true,
|
|
17
|
+
"outDir": "./dist",
|
|
18
|
+
"allowSyntheticDefaultImports": true,
|
|
19
|
+
"esModuleInterop": true,
|
|
20
|
+
"forceConsistentCasingInFileNames": true
|
|
21
|
+
},
|
|
22
|
+
"include": ["src/**/*", "typings/**/*"],
|
|
23
|
+
"exclude": ["node_modules", "dist"]
|
|
24
|
+
}
|
package/tsdown.config.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { defineConfig } from 'tsdown'
|
|
2
|
+
|
|
3
|
+
export default defineConfig([
|
|
4
|
+
{
|
|
5
|
+
name: 'qvite-api',
|
|
6
|
+
outDir: 'dist',
|
|
7
|
+
entry: ['index.ts'],
|
|
8
|
+
platform: 'node',
|
|
9
|
+
minify: false,
|
|
10
|
+
dts: true
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
name: 'qvite-cli',
|
|
14
|
+
outDir: 'dist/bin',
|
|
15
|
+
platform: 'node',
|
|
16
|
+
dts: false,
|
|
17
|
+
minify: false,
|
|
18
|
+
entry: { qvite: 'cli.ts' }
|
|
19
|
+
}
|
|
20
|
+
])
|