feat: support config.extends

pull/389/head
Evan You 3 years ago
parent 2e9264f032
commit f749b272d4

@ -2,7 +2,11 @@ import path from 'path'
import fs from 'fs-extra' import fs from 'fs-extra'
import chalk from 'chalk' import chalk from 'chalk'
import globby from 'globby' import globby from 'globby'
import { AliasOptions, UserConfig as ViteConfig } from 'vite' import {
AliasOptions,
UserConfig as ViteConfig,
mergeConfig as mergeViteConfig
} from 'vite'
import { Options as VuePluginOptions } from '@vitejs/plugin-vue' import { Options as VuePluginOptions } from '@vitejs/plugin-vue'
import { import {
SiteData, SiteData,
@ -47,8 +51,15 @@ export interface UserConfig<ThemeConfig = any> {
* @deprecated use `vue` instead * @deprecated use `vue` instead
*/ */
vueOptions?: VuePluginOptions vueOptions?: VuePluginOptions
extends?: RawConfigExports
} }
type RawConfigExports =
| UserConfig
| Promise<UserConfig>
| (() => UserConfig | Promise<UserConfig>)
export interface SiteConfig<ThemeConfig = any> { export interface SiteConfig<ThemeConfig = any> {
root: string root: string
srcDir: string srcDir: string
@ -122,16 +133,53 @@ export async function resolveUserConfig(root: string): Promise<UserConfig> {
const hasUserConfig = await fs.pathExists(configPath) const hasUserConfig = await fs.pathExists(configPath)
// always delete cache first before loading config // always delete cache first before loading config
delete require.cache[configPath] delete require.cache[configPath]
const userConfig: UserConfig | (() => UserConfig) = hasUserConfig const userConfig: RawConfigExports = hasUserConfig ? require(configPath) : {}
? require(configPath)
: {}
if (hasUserConfig) { if (hasUserConfig) {
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)
}
async function resolveConfigExtends(
config: RawConfigExports
): Promise<UserConfig> {
const resolved = await (typeof config === 'function' ? config() : config)
if (resolved.extends) {
const base = await resolveConfigExtends(resolved.extends)
return mergeConfig(base, resolved)
}
return resolved
}
function mergeConfig(a: UserConfig, b: UserConfig, isRoot = true) {
const merged: Record<string, any> = { ...a }
for (const key in b) {
const value = b[key as keyof UserConfig]
if (value == null) {
continue
}
const existing = merged[key]
if (Array.isArray(existing) && Array.isArray(value)) {
merged[key] = [...existing, ...value]
continue
}
if (isObject(existing) && isObject(value)) {
if (isRoot && key === 'vite') {
merged[key] = mergeViteConfig(existing, value)
} else {
merged[key] = mergeConfig(existing, value, false)
}
continue
}
merged[key] = value
}
return merged
}
return typeof userConfig === 'function' ? userConfig() : userConfig function isObject(value: unknown): value is Record<string, any> {
return Object.prototype.toString.call(value) === '[object Object]'
} }
export async function resolveSiteData( export async function resolveSiteData(

Loading…
Cancel
Save