feat: support ts/esm config file + defineConfig() helper

close #339, close #376
pull/421/head
Evan You 3 years ago
parent 4c042b61e7
commit d3b1521ebe

@ -1,4 +1,4 @@
module.exports = { export default {
lang: 'en-US', lang: 'en-US',
title: 'VitePress', title: 'VitePress',
description: 'Vite & Vue powered static site generator.', description: 'Vite & Vue powered static site generator.',

@ -13,7 +13,7 @@ export async function build(
const start = Date.now() const start = Date.now()
process.env.NODE_ENV = 'production' process.env.NODE_ENV = 'production'
const siteConfig = await resolveConfig(root) const siteConfig = await resolveConfig(root, 'build', 'production')
if (buildOptions.mpa) { if (buildOptions.mpa) {
siteConfig.mpa = true siteConfig.mpa = true

@ -6,7 +6,8 @@ import {
normalizePath, normalizePath,
AliasOptions, AliasOptions,
UserConfig as ViteConfig, UserConfig as ViteConfig,
mergeConfig as mergeViteConfig mergeConfig as mergeViteConfig,
loadConfigFromFile
} from 'vite' } from 'vite'
import { Options as VuePluginOptions } from '@vitejs/plugin-vue' import { Options as VuePluginOptions } from '@vitejs/plugin-vue'
import { import {
@ -63,7 +64,7 @@ export interface SiteConfig<ThemeConfig = any> {
root: string root: string
srcDir: string srcDir: string
site: SiteData<ThemeConfig> site: SiteData<ThemeConfig>
configPath: string configPath: string | undefined
themeDir: string themeDir: string
outDir: string outDir: string
tempDir: string tempDir: string
@ -78,10 +79,19 @@ export interface SiteConfig<ThemeConfig = any> {
const resolve = (root: string, file: string) => const resolve = (root: string, file: string) =>
normalizePath(path.resolve(root, `.vitepress`, file)) normalizePath(path.resolve(root, `.vitepress`, file))
/**
* Type config helper
*/
export function defineConfig(config: RawConfigExports) {
return config
}
export async function resolveConfig( export async function resolveConfig(
root: string = process.cwd() root: string = process.cwd(),
command: 'serve' | 'build' = 'serve',
mode = 'development'
): Promise<SiteConfig> { ): Promise<SiteConfig> {
const userConfig = await resolveUserConfig(root) const [userConfig, configPath] = await resolveUserConfig(root, command, mode)
const site = await resolveSiteData(root, userConfig) const site = await resolveSiteData(root, userConfig)
const srcDir = path.resolve(root, userConfig.srcDir || '.') const srcDir = path.resolve(root, userConfig.srcDir || '.')
@ -110,7 +120,7 @@ export async function resolveConfig(
site, site,
themeDir, themeDir,
pages, pages,
configPath: resolve(root, 'config.js'), configPath,
outDir: resolve(root, 'dist'), outDir: resolve(root, 'dist'),
tempDir: path.resolve(APP_PATH, 'temp'), tempDir: path.resolve(APP_PATH, 'temp'),
markdown: userConfig.markdown, markdown: userConfig.markdown,
@ -123,19 +133,43 @@ export async function resolveConfig(
return config return config
} }
export async function resolveUserConfig(root: string): Promise<UserConfig> { const supportedConfigExtensions = ['js', 'ts', '.mjs', 'mts']
async function resolveUserConfig(
root: string,
command: 'serve' | 'build',
mode: string
): Promise<[UserConfig, string | undefined]> {
// load user config // load user config
const configPath = resolve(root, 'config.js') let configPath
const hasUserConfig = await fs.pathExists(configPath) for (const ext of supportedConfigExtensions) {
// always delete cache first before loading config const p = resolve(root, `config.${ext}`)
delete require.cache[require.resolve(configPath)] if (await fs.pathExists(p)) {
const userConfig: RawConfigExports = hasUserConfig ? require(configPath) : {} configPath = p
if (hasUserConfig) { break
}
}
const userConfig: RawConfigExports = configPath
? ((
await loadConfigFromFile(
{
command,
mode
},
configPath,
root
)
)?.config as any)
: {}
if (configPath) {
debug(`loaded config at ${chalk.yellow(configPath)}`) debug(`loaded config at ${chalk.yellow(configPath)}`)
} else { } else {
debug(`no config file found.`) debug(`no config file found.`)
} }
return resolveConfigExtends(userConfig)
return [await resolveConfigExtends(userConfig), configPath]
} }
async function resolveConfigExtends( async function resolveConfigExtends(
@ -180,9 +214,11 @@ function isObject(value: unknown): value is Record<string, any> {
export async function resolveSiteData( export async function resolveSiteData(
root: string, root: string,
userConfig?: UserConfig userConfig?: UserConfig,
command: 'serve' | 'build' = 'serve',
mode = 'development'
): Promise<SiteData> { ): Promise<SiteData> {
userConfig = userConfig || (await resolveUserConfig(root)) userConfig = userConfig || (await resolveUserConfig(root, command, mode))[0]
return { return {
lang: userConfig.lang || 'en-US', lang: userConfig.lang || 'en-US',
title: userConfig.title || 'VitePress', title: userConfig.title || 'VitePress',

@ -154,7 +154,9 @@ export function createVitePressPlugin(
}, },
configureServer(server) { configureServer(server) {
if (configPath) {
server.watcher.add(configPath) server.watcher.add(configPath)
}
// serve our index.html after vite history fallback // serve our index.html after vite history fallback
return () => { return () => {

@ -10,7 +10,7 @@ export interface ServeOptions {
export async function serve(options: ServeOptions = {}) { export async function serve(options: ServeOptions = {}) {
const port = options.port !== undefined ? options.port : 5000 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 compress = compression()
const serve = sirv(site.outDir, { const serve = sirv(site.outDir, {

Loading…
Cancel
Save