feat(config): support configuring runtime compiler via app.config.compilerOptions

- `config.isCustomElement` is deprecated - use `app.config.compilerOptions.isCustomElement` instead.
This commit is contained in:
Evan You 2021-04-26 11:46:29 -04:00
parent b047a0864c
commit 091e6d67bf
4 changed files with 85 additions and 18 deletions

View File

@ -69,7 +69,6 @@ export interface AppConfig {
performance: boolean performance: boolean
optionMergeStrategies: Record<string, OptionMergeFunction> optionMergeStrategies: Record<string, OptionMergeFunction>
globalProperties: Record<string, any> globalProperties: Record<string, any>
isCustomElement: (tag: string) => boolean
errorHandler?: ( errorHandler?: (
err: unknown, err: unknown,
instance: ComponentPublicInstance | null, instance: ComponentPublicInstance | null,
@ -80,6 +79,22 @@ export interface AppConfig {
instance: ComponentPublicInstance | null, instance: ComponentPublicInstance | null,
trace: string trace: string
) => void ) => void
/**
* @deprecated use config.compilerOptions.isCustomElement
*/
isCustomElement?: (tag: string) => boolean
/**
* Options to pass to @vue/compiler-dom.
* *Only supported in runtime compiler build.*
*/
compilerOptions: {
isCustomElement: (tag: string) => boolean
whitespace?: 'preserve' | 'condense'
comments?: boolean
delimiters?: [string, string]
}
} }
export interface AppContext { export interface AppContext {
@ -122,9 +137,11 @@ export function createAppContext(): AppContext {
performance: false, performance: false,
globalProperties: {}, globalProperties: {},
optionMergeStrategies: {}, optionMergeStrategies: {},
isCustomElement: NO,
errorHandler: undefined, errorHandler: undefined,
warnHandler: undefined warnHandler: undefined,
compilerOptions: {
isCustomElement: NO
}
}, },
mixins: [], mixins: [],
components: {}, components: {},

View File

@ -727,18 +727,22 @@ export function finishComponentSetup(
if (__DEV__) { if (__DEV__) {
startMeasure(instance, `compile`) startMeasure(instance, `compile`)
} }
const compilerOptions: CompilerOptions = { const { isCustomElement, compilerOptions } = instance.appContext.config
isCustomElement: instance.appContext.config.isCustomElement, const finalCompilerOptions: CompilerOptions = extend(
delimiters: Component.delimiters {
} isCustomElement: isCustomElement || NO,
delimiters: Component.delimiters
},
compilerOptions
)
if (__COMPAT__) { if (__COMPAT__) {
// pass runtime compat config into the compiler // pass runtime compat config into the compiler
compilerOptions.compatConfig = Object.create(globalCompatConfig) finalCompilerOptions.compatConfig = Object.create(globalCompatConfig)
if (Component.compatConfig) { if (Component.compatConfig) {
extend(compilerOptions.compatConfig, Component.compatConfig) extend(finalCompilerOptions.compatConfig, Component.compatConfig)
} }
} }
Component.render = compile(template, compilerOptions) Component.render = compile(template, finalCompilerOptions)
if (__DEV__) { if (__DEV__) {
endMeasure(instance, `compile`) endMeasure(instance, `compile`)
} }

View File

@ -58,7 +58,7 @@ export const createApp = ((...args) => {
if (__DEV__) { if (__DEV__) {
injectNativeTagCheck(app) injectNativeTagCheck(app)
injectCustomElementCheck(app) injectCompilerOptionsCheck(app)
} }
const { mount } = app const { mount } = app
@ -106,7 +106,7 @@ export const createSSRApp = ((...args) => {
if (__DEV__) { if (__DEV__) {
injectNativeTagCheck(app) injectNativeTagCheck(app)
injectCustomElementCheck(app) injectCompilerOptionsCheck(app)
} }
const { mount } = app const { mount } = app
@ -130,21 +130,40 @@ function injectNativeTagCheck(app: App) {
} }
// dev only // dev only
function injectCustomElementCheck(app: App) { function injectCompilerOptionsCheck(app: App) {
if (isRuntimeOnly()) { if (isRuntimeOnly()) {
const value = app.config.isCustomElement const isCustomElement = app.config.isCustomElement
Object.defineProperty(app.config, 'isCustomElement', { Object.defineProperty(app.config, 'isCustomElement', {
get() { get() {
return value return isCustomElement
}, },
set() { set() {
warn( warn(
`The \`isCustomElement\` config option is only respected when using the runtime compiler.` + `The \`isCustomElement\` config option is deprecated. Use ` +
`If you are using the runtime-only build, \`isCustomElement\` must be passed to \`@vue/compiler-dom\` in the build setup instead` + `\`compilerOptions.isCustomElement\` instead.`
`- for example, via the \`compilerOptions\` option in vue-loader: https://vue-loader.vuejs.org/options.html#compileroptions.`
) )
} }
}) })
const compilerOptions = app.config.compilerOptions
const msg =
`The \`compilerOptions\` config option is only respected when using ` +
`a build of Vue.js that includes the runtime compiler (aka "full build"). ` +
`Since you are using the runtime-only build, \`compilerOptions\` ` +
`must be passed to \`@vue/compiler-dom\` in the build setup instead.\n` +
`- For vue-loader: pass it via vue-loader's \`compilerOptions\` loader option.\n` +
`- For vue-cli: see https://cli.vuejs.org/guide/webpack.html#modifying-options-of-a-loader\n` +
`- For vite: pass it via @vitejs/plugin-vue options. See https://github.com/vitejs/vite/tree/main/packages/plugin-vue#example-for-passing-options-to-vuecompiler-dom`
Object.defineProperty(app.config, 'compilerOptions', {
get() {
warn(msg)
return compilerOptions
},
set() {
warn(msg)
}
})
} }
} }

View File

@ -14,6 +14,7 @@ export const compilerOptions: CompilerOptions = reactive({
inline: false, inline: false,
ssrCssVars: `{ color }`, ssrCssVars: `{ color }`,
compatConfig: { MODE: 3 }, compatConfig: { MODE: 3 },
whitespace: 'condense',
bindingMetadata: { bindingMetadata: {
TestComponent: BindingTypes.SETUP_CONST, TestComponent: BindingTypes.SETUP_CONST,
setupRef: BindingTypes.SETUP_REF, setupRef: BindingTypes.SETUP_REF,
@ -83,6 +84,32 @@ const App = {
h('label', { for: 'mode-function' }, 'function') h('label', { for: 'mode-function' }, 'function')
]), ]),
// whitespace handling
h('li', { id: 'whitespace' }, [
h('span', { class: 'label' }, 'whitespace: '),
h('input', {
type: 'radio',
id: 'whitespace-condense',
name: 'whitespace',
checked: compilerOptions.whitespace === 'condense',
onChange() {
compilerOptions.whitespace = 'condense'
}
}),
h('label', { for: 'whitespace-condense' }, 'condense'),
' ',
h('input', {
type: 'radio',
id: 'whitespace-preserve',
name: 'whitespace',
checked: compilerOptions.whitespace === 'preserve',
onChange() {
compilerOptions.whitespace = 'preserve'
}
}),
h('label', { for: 'whitespace-preserve' }, 'preserve')
]),
// SSR // SSR
h('li', [ h('li', [
h('input', { h('input', {