wip: initial compat build setup

This commit is contained in:
Evan You
2021-04-03 11:55:44 -04:00
parent 870f2a7ba3
commit 24850a99c6
14 changed files with 431 additions and 18 deletions

View File

@@ -0,0 +1 @@
# @vue/compat

View File

@@ -0,0 +1,7 @@
{
"extends": "../../api-extractor.json",
"mainEntryPointFilePath": "./dist/packages/<unscopedPackageName>/src/index.d.ts",
"dtsRollup": {
"publicTrimmedFilePath": "./dist/<unscopedPackageName>.d.ts"
}
}

View File

@@ -0,0 +1,7 @@
'use strict'
if (process.env.NODE_ENV === 'production') {
module.exports = require('./dist/compat.cjs.prod.js')
} else {
module.exports = require('./dist/compat.cjs.js')
}

View File

@@ -0,0 +1,44 @@
{
"name": "@vue/compat",
"version": "3.0.11",
"description": "@vue/compat",
"main": "index.js",
"module": "dist/vue.esm-bundler.js",
"types": "dist/vue.d.ts",
"unpkg": "dist/vue.global.js",
"jsdelivr": "dist/vue.global.js",
"files": [
"index.js",
"dist"
],
"buildOptions": {
"name": "Vue",
"filename": "vue",
"compat": true,
"formats": [
"esm-bundler",
"esm-bundler-runtime",
"cjs",
"global",
"global-runtime",
"esm-browser",
"esm-browser-runtime"
]
},
"repository": {
"type": "git",
"url": "git+https://github.com/vuejs/vue.git"
},
"keywords": [
"vue"
],
"author": "Evan You",
"license": "MIT",
"bugs": {
"url": "https://github.com/vuejs/vue/issues"
},
"homepage": "https://github.com/vuejs/vue/tree/dev/packages/vue-compat#readme",
"peerDependencies": {
"vue": "3.0.11"
}
}

View File

@@ -0,0 +1,157 @@
import { reactive } from '@vue/reactivity'
import {
createApp,
defineComponent,
nextTick,
App,
AppConfig,
Plugin,
Component,
ComponentOptions,
ComponentPublicInstance,
Directive,
RenderFunction,
isRuntimeOnly
} from '@vue/runtime-dom'
// TODO make these getter/setters and trigger deprecation warnings
export type LegacyConfig = AppConfig & {
/**
* @deprecated `config.silent` option has been removed
*/
silent?: boolean
/**
* @deprecated use __VUE_PROD_DEVTOOLS__ compile-time feature flag instead
* https://github.com/vuejs/vue-next/tree/master/packages/vue#bundler-build-feature-flags
*/
devtools?: boolean
/**
* @deprecated use `config.isCustomElement` instead
* https://v3.vuejs.org/guide/migration/global-api.html#config-ignoredelements-is-now-config-iscustomelement
*/
ignoredElements?: (string | RegExp)[]
/**
* @deprecated
* https://v3.vuejs.org/guide/migration/keycode-modifiers.html
*/
keyCodes?: Record<string, number | number[]>
/**
* @deprecated
* https://v3.vuejs.org/guide/migration/global-api.html#config-productiontip-removed
*/
productionTip?: boolean
}
/**
* @deprecated the default `Vue` export has been removed in Vue 3. The type for
* the default export is provided only for migration purposes. Please use
* named imports instead - e.g. `import { createApp } from 'vue'`.
*/
export type GlobalVue = Pick<App, 'version' | 'component' | 'directive'> & {
// no inference here since these types are not meant for actual use - they
// are merely here to provide type checks for internal implementation and
// information for migration.
new (options?: ComponentOptions): ComponentPublicInstance
version: string
config: LegacyConfig
extend: typeof defineComponent
nextTick: typeof nextTick
use(plugin: Plugin, ...options: any[]): GlobalVue
mixin(mixin: ComponentOptions): GlobalVue
component(name: string): Component | undefined
component(name: string, component: Component): GlobalVue
directive(name: string): Directive | undefined
directive(name: string, directive: Directive): GlobalVue
compile(template: string): RenderFunction
/**
* @deprecated Vue 3 no longer needs set() for adding new properties.
*/
set(target: any, key: string | number | symbol, value: any): void
/**
* @deprecated Vue 3 no longer needs delete() for property deletions.
*/
delete(target: any, key: string | number | symbol): void
/**
* @deprecated use `reactive` instead.
*/
observable: typeof reactive
/**
* @deprecated filters have been removed from Vue 3.
*/
filter(name: string, arg: any): null
}
export const Vue: GlobalVue = function Vue(options: ComponentOptions = {}) {
const app = createApp(options)
// copy over global config mutations
for (const key in singletonApp.config) {
if (
key !== 'isNativeTag' &&
!(key === 'isCustomElement' && isRuntimeOnly())
) {
// @ts-ignore
app.config[key] = singletonApp.config[key]
}
}
if (options.el) {
return app.mount(options.el)
}
} as any
const singletonApp = createApp({})
Vue.version = __VERSION__
Vue.config = singletonApp.config
Vue.extend = defineComponent
Vue.nextTick = nextTick
Vue.set = (target, key, value) => {
// TODO deprecation warnings
target[key] = value
}
Vue.delete = (target, key) => {
// TODO deprecation warnings
delete target[key]
}
// TODO wrap with deprecation warning
Vue.observable = reactive
Vue.use = (p, ...options) => {
singletonApp.use(p, ...options)
return Vue
}
Vue.mixin = m => {
singletonApp.mixin(m)
return Vue
}
Vue.component = ((name: string, comp: any) => {
if (comp) {
singletonApp.component(name, comp)
return Vue
} else {
return singletonApp.component(name)
}
}) as any
Vue.directive = ((name: string, dir: any) => {
if (dir) {
singletonApp.directive(name, dir)
return Vue
} else {
return singletonApp.directive(name)
}
}) as any
Vue.filter = ((name: string, filter: any) => {
// TODO deprecation warning
// TODO compiler warning for filters (maybe behavior compat?)
}) as any

View File

@@ -0,0 +1,14 @@
import { initCustomFormatter } from '@vue/runtime-dom'
export function initDev() {
if (__BROWSER__) {
if (!__ESM_BUNDLER__) {
console.info(
`You are running a development build of Vue.\n` +
`Make sure to use the production build (*.prod.js) when deploying for production.`
)
}
initCustomFormatter()
}
}

View File

@@ -0,0 +1,93 @@
// This entry is the "full-build" that includes both the runtime
// and the compiler, and supports on-the-fly compilation of the template option.
import { initDev } from './dev'
import { compile, CompilerOptions, CompilerError } from '@vue/compiler-dom'
import { registerRuntimeCompiler, RenderFunction, warn } from '@vue/runtime-dom'
import { isString, NOOP, generateCodeFrame, extend } from '@vue/shared'
import { InternalRenderFunction } from 'packages/runtime-core/src/component'
import * as runtimeDom from '@vue/runtime-dom'
import { Vue } from './apiGlobal'
if (__DEV__) {
initDev()
}
const compileCache: Record<string, RenderFunction> = Object.create(null)
function compileToFunction(
template: string | HTMLElement,
options?: CompilerOptions
): RenderFunction {
if (!isString(template)) {
if (template.nodeType) {
template = template.innerHTML
} else {
__DEV__ && warn(`invalid template option: `, template)
return NOOP
}
}
const key = template
const cached = compileCache[key]
if (cached) {
return cached
}
if (template[0] === '#') {
const el = document.querySelector(template)
if (__DEV__ && !el) {
warn(`Template element not found or is empty: ${template}`)
}
// __UNSAFE__
// Reason: potential execution of JS expressions in in-DOM template.
// The user must make sure the in-DOM template is trusted. If it's rendered
// by the server, the template should not contain any user data.
template = el ? el.innerHTML : ``
}
const { code } = compile(
template,
extend(
{
hoistStatic: true,
onError(err: CompilerError) {
if (__DEV__) {
const message = `Template compilation error: ${err.message}`
const codeFrame =
err.loc &&
generateCodeFrame(
template as string,
err.loc.start.offset,
err.loc.end.offset
)
warn(codeFrame ? `${message}\n${codeFrame}` : message)
} else {
/* istanbul ignore next */
throw err
}
}
},
options
)
)
// The wildcard import results in a huge object with every export
// with keys that cannot be mangled, and can be quite heavy size-wise.
// In the global build we know `Vue` is available globally so we can avoid
// the wildcard object.
const render = (__GLOBAL__
? new Function(code)()
: new Function('Vue', code)(runtimeDom)) as RenderFunction
// mark the function as runtime compiled
;(render as InternalRenderFunction)._rc = true
return (compileCache[key] = render)
}
registerRuntimeCompiler(compileToFunction)
Vue.compile = compileToFunction
extend(Vue, runtimeDom)
export default Vue

View File

@@ -0,0 +1,25 @@
// This entry exports the runtime only, and is built as
// `dist/vue.esm-bundler.js` which is used by default for bundlers.
import { initDev } from './dev'
import { warn } from '@vue/runtime-dom'
if (__DEV__) {
initDev()
}
export * from '@vue/runtime-dom'
export const compile = () => {
if (__DEV__) {
warn(
`Runtime compilation is not supported in this build of Vue.` +
(__ESM_BUNDLER__
? ` Configure your bundler to alias "vue" to "@vue/compat/dist/vue.esm-bundler.js".`
: __ESM_BROWSER__
? ` Use "vue.esm-browser.js" instead.`
: __GLOBAL__
? ` Use "vue.global.js" instead.`
: ``) /* should not happen */
)
}
}