From d3b1521ebef831e0d0307b3b12e4fc1f6ce4721a Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 7 Oct 2021 19:18:20 -0400 Subject: [PATCH] feat: support ts/esm config file + defineConfig() helper close #339, close #376 --- docs/.vitepress/{config.js => config.ts} | 2 +- src/node/build/build.ts | 2 +- src/node/config.ts | 66 ++++++++++++++++++------ src/node/plugin.ts | 4 +- src/node/serve/serve.ts | 2 +- 5 files changed, 57 insertions(+), 19 deletions(-) rename docs/.vitepress/{config.js => config.ts} (99%) diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.ts similarity index 99% rename from docs/.vitepress/config.js rename to docs/.vitepress/config.ts index b1db2393..b680ece5 100644 --- a/docs/.vitepress/config.js +++ b/docs/.vitepress/config.ts @@ -1,4 +1,4 @@ -module.exports = { +export default { lang: 'en-US', title: 'VitePress', description: 'Vite & Vue powered static site generator.', diff --git a/src/node/build/build.ts b/src/node/build/build.ts index a8934b1e..7ed05aea 100644 --- a/src/node/build/build.ts +++ b/src/node/build/build.ts @@ -13,7 +13,7 @@ export async function build( const start = Date.now() process.env.NODE_ENV = 'production' - const siteConfig = await resolveConfig(root) + const siteConfig = await resolveConfig(root, 'build', 'production') if (buildOptions.mpa) { siteConfig.mpa = true diff --git a/src/node/config.ts b/src/node/config.ts index d48e0ddc..4fdc2117 100644 --- a/src/node/config.ts +++ b/src/node/config.ts @@ -6,7 +6,8 @@ import { normalizePath, AliasOptions, UserConfig as ViteConfig, - mergeConfig as mergeViteConfig + mergeConfig as mergeViteConfig, + loadConfigFromFile } from 'vite' import { Options as VuePluginOptions } from '@vitejs/plugin-vue' import { @@ -63,7 +64,7 @@ export interface SiteConfig { root: string srcDir: string site: SiteData - configPath: string + configPath: string | undefined themeDir: string outDir: string tempDir: string @@ -78,10 +79,19 @@ export interface SiteConfig { const resolve = (root: string, file: string) => normalizePath(path.resolve(root, `.vitepress`, file)) +/** + * Type config helper + */ +export function defineConfig(config: RawConfigExports) { + return config +} + export async function resolveConfig( - root: string = process.cwd() + root: string = process.cwd(), + command: 'serve' | 'build' = 'serve', + mode = 'development' ): Promise { - const userConfig = await resolveUserConfig(root) + const [userConfig, configPath] = await resolveUserConfig(root, command, mode) const site = await resolveSiteData(root, userConfig) const srcDir = path.resolve(root, userConfig.srcDir || '.') @@ -110,7 +120,7 @@ export async function resolveConfig( site, themeDir, pages, - configPath: resolve(root, 'config.js'), + configPath, outDir: resolve(root, 'dist'), tempDir: path.resolve(APP_PATH, 'temp'), markdown: userConfig.markdown, @@ -123,19 +133,43 @@ export async function resolveConfig( return config } -export async function resolveUserConfig(root: string): Promise { +const supportedConfigExtensions = ['js', 'ts', '.mjs', 'mts'] + +async function resolveUserConfig( + root: string, + command: 'serve' | 'build', + mode: string +): Promise<[UserConfig, string | undefined]> { // load user config - const configPath = resolve(root, 'config.js') - const hasUserConfig = await fs.pathExists(configPath) - // always delete cache first before loading config - delete require.cache[require.resolve(configPath)] - const userConfig: RawConfigExports = hasUserConfig ? require(configPath) : {} - if (hasUserConfig) { + let configPath + for (const ext of supportedConfigExtensions) { + const p = resolve(root, `config.${ext}`) + if (await fs.pathExists(p)) { + configPath = p + break + } + } + + const userConfig: RawConfigExports = configPath + ? (( + await loadConfigFromFile( + { + command, + mode + }, + configPath, + root + ) + )?.config as any) + : {} + + if (configPath) { debug(`loaded config at ${chalk.yellow(configPath)}`) } else { debug(`no config file found.`) } - return resolveConfigExtends(userConfig) + + return [await resolveConfigExtends(userConfig), configPath] } async function resolveConfigExtends( @@ -180,9 +214,11 @@ function isObject(value: unknown): value is Record { export async function resolveSiteData( root: string, - userConfig?: UserConfig + userConfig?: UserConfig, + command: 'serve' | 'build' = 'serve', + mode = 'development' ): Promise { - userConfig = userConfig || (await resolveUserConfig(root)) + userConfig = userConfig || (await resolveUserConfig(root, command, mode))[0] return { lang: userConfig.lang || 'en-US', title: userConfig.title || 'VitePress', diff --git a/src/node/plugin.ts b/src/node/plugin.ts index e3ce80ae..6f1751e7 100644 --- a/src/node/plugin.ts +++ b/src/node/plugin.ts @@ -154,7 +154,9 @@ export function createVitePressPlugin( }, configureServer(server) { - server.watcher.add(configPath) + if (configPath) { + server.watcher.add(configPath) + } // serve our index.html after vite history fallback return () => { diff --git a/src/node/serve/serve.ts b/src/node/serve/serve.ts index 81b57c3a..fe84e965 100644 --- a/src/node/serve/serve.ts +++ b/src/node/serve/serve.ts @@ -10,7 +10,7 @@ export interface ServeOptions { export async function serve(options: ServeOptions = {}) { const port = options.port !== undefined ? options.port : 5000 - const site = await resolveConfig(options.root) + const site = await resolveConfig(options.root, 'serve', 'production') const compress = compression() const serve = sirv(site.outDir, {