mirror of
https://github.com/nuxt/nuxt.git
synced 2025-02-22 16:39:58 +00:00
perf(nuxt)!: remove legacy app context (#5630)
This commit is contained in:
parent
dd436eabae
commit
b5f5f7d5ba
@ -1,215 +0,0 @@
|
|||||||
import type { IncomingMessage, ServerResponse } from 'node:http'
|
|
||||||
import type { App } from 'vue'
|
|
||||||
import type { Component } from '@vue/runtime-core'
|
|
||||||
import mockContext from 'unenv/runtime/mock/proxy'
|
|
||||||
import type { RouteLocationNormalized, Router } from 'vue-router'
|
|
||||||
import { NuxtApp, useRuntimeConfig } from '../nuxt'
|
|
||||||
|
|
||||||
type Store = any
|
|
||||||
|
|
||||||
export type LegacyApp = App<Element> & {
|
|
||||||
$root: LegacyApp
|
|
||||||
constructor: LegacyApp
|
|
||||||
$router?: Router
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LegacyContext {
|
|
||||||
// -> $config
|
|
||||||
$config: Record<string, any>
|
|
||||||
env: Record<string, any>
|
|
||||||
// -> app
|
|
||||||
app: Component
|
|
||||||
// -> unsupported
|
|
||||||
isClient: boolean
|
|
||||||
isServer: boolean
|
|
||||||
isStatic: boolean
|
|
||||||
// TODO: needs app implementation
|
|
||||||
isDev: boolean
|
|
||||||
isHMR: boolean
|
|
||||||
// -> unsupported
|
|
||||||
store: Store
|
|
||||||
// vue-router integration
|
|
||||||
route: RouteLocationNormalized
|
|
||||||
params: RouteLocationNormalized['params']
|
|
||||||
query: RouteLocationNormalized['query']
|
|
||||||
base: string /** TODO: */
|
|
||||||
payload: any /** TODO: */
|
|
||||||
from: RouteLocationNormalized /** TODO: */
|
|
||||||
// -> nuxt.payload.data
|
|
||||||
nuxtState: Record<string, any>
|
|
||||||
// TODO: needs app implementation
|
|
||||||
beforeNuxtRender (fn: (params: { Components: any, nuxtState: Record<string, any> }) => void): void
|
|
||||||
beforeSerialize (fn: (nuxtState: Record<string, any>) => void): void
|
|
||||||
// TODO: needs app implementation
|
|
||||||
enablePreview?: (previewData?: Record<string, any>) => void
|
|
||||||
$preview?: Record<string, any>
|
|
||||||
// -> ssrContext.{req,res}
|
|
||||||
req: IncomingMessage
|
|
||||||
res: ServerResponse
|
|
||||||
/** TODO: */
|
|
||||||
next?: (err?: any) => any
|
|
||||||
error (params: any): void
|
|
||||||
redirect (status: number, path: string, query?: RouteLocationNormalized['query']): void
|
|
||||||
redirect (path: string, query?: RouteLocationNormalized['query']): void
|
|
||||||
redirect (location: Location): void
|
|
||||||
redirect (status: number, location: Location): void
|
|
||||||
ssrContext?: {
|
|
||||||
// -> ssrContext.{req,res,url,runtimeConfig}
|
|
||||||
req: LegacyContext['req']
|
|
||||||
res: LegacyContext['res']
|
|
||||||
url: string
|
|
||||||
runtimeConfig: {
|
|
||||||
public: Record<string, any>
|
|
||||||
private: Record<string, any>
|
|
||||||
}
|
|
||||||
// -> unsupported
|
|
||||||
target: string
|
|
||||||
spa?: boolean
|
|
||||||
modern: boolean
|
|
||||||
fetchCounters: Record<string, number>
|
|
||||||
// TODO:
|
|
||||||
next: LegacyContext['next']
|
|
||||||
redirected: boolean
|
|
||||||
beforeRenderFns: Array<() => any>
|
|
||||||
beforeSerializeFns: Array<() => any>
|
|
||||||
// -> nuxt.payload
|
|
||||||
nuxt: {
|
|
||||||
serverRendered: boolean
|
|
||||||
// TODO:
|
|
||||||
layout: string
|
|
||||||
data: Array<Record<string, any>>
|
|
||||||
fetch: Array<Record<string, any>>
|
|
||||||
error: any
|
|
||||||
state: Array<Record<string, any>>
|
|
||||||
routePath: string
|
|
||||||
config: Record<string, any>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function mock (warning: string) {
|
|
||||||
console.warn(warning)
|
|
||||||
return mockContext
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsupported = new Set<keyof LegacyContext | keyof LegacyContext['ssrContext']>([
|
|
||||||
'store',
|
|
||||||
'spa',
|
|
||||||
'fetchCounters'
|
|
||||||
])
|
|
||||||
|
|
||||||
const todo = new Set<keyof LegacyContext | keyof LegacyContext['ssrContext']>([
|
|
||||||
'isHMR',
|
|
||||||
// Routing handlers - needs implementation or deprecation
|
|
||||||
'base',
|
|
||||||
'payload',
|
|
||||||
'from',
|
|
||||||
'next',
|
|
||||||
'error',
|
|
||||||
'redirect',
|
|
||||||
'redirected',
|
|
||||||
// needs app implementation
|
|
||||||
'enablePreview',
|
|
||||||
'$preview',
|
|
||||||
'beforeNuxtRender',
|
|
||||||
'beforeSerialize'
|
|
||||||
])
|
|
||||||
|
|
||||||
const serverProperties = new Set<keyof LegacyContext['ssrContext'] | keyof LegacyContext>([
|
|
||||||
'req',
|
|
||||||
'res',
|
|
||||||
'ssrContext'
|
|
||||||
])
|
|
||||||
|
|
||||||
const routerKeys: Array<keyof LegacyContext | keyof LegacyContext['ssrContext']> = ['route', 'params', 'query']
|
|
||||||
|
|
||||||
const staticFlags = {
|
|
||||||
isClient: process.client,
|
|
||||||
isServer: process.server,
|
|
||||||
isDev: process.dev,
|
|
||||||
isStatic: undefined,
|
|
||||||
target: 'server',
|
|
||||||
modern: false
|
|
||||||
}
|
|
||||||
|
|
||||||
export const legacyPlugin = (nuxtApp: NuxtApp) => {
|
|
||||||
nuxtApp._legacyContext = new Proxy(nuxtApp, {
|
|
||||||
get (nuxt, p: keyof LegacyContext | keyof LegacyContext['ssrContext']) {
|
|
||||||
// Unsupported keys
|
|
||||||
if (unsupported.has(p)) {
|
|
||||||
return mock(`Accessing ${p} is not supported in Nuxt 3.`)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (todo.has(p)) {
|
|
||||||
return mock(`Accessing ${p} is not yet supported in Nuxt 3.`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// vue-router implementation
|
|
||||||
if (routerKeys.includes(p)) {
|
|
||||||
if (!('$router' in nuxtApp)) {
|
|
||||||
return mock('vue-router is not being used in this project.')
|
|
||||||
}
|
|
||||||
switch (p) {
|
|
||||||
case 'route':
|
|
||||||
return nuxt.$router.currentRoute.value
|
|
||||||
case 'params':
|
|
||||||
case 'query':
|
|
||||||
return nuxt.$router.currentRoute.value[p]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p === '$config' || p === 'env') {
|
|
||||||
return useRuntimeConfig()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p in staticFlags) {
|
|
||||||
return staticFlags[p]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.client && serverProperties.has(p)) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p === 'ssrContext') {
|
|
||||||
return nuxt._legacyContext
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nuxt.ssrContext && p in nuxt.ssrContext) {
|
|
||||||
return nuxt.ssrContext[p]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p === 'nuxt') {
|
|
||||||
return nuxt.payload
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p === 'nuxtState') {
|
|
||||||
return nuxt.payload.data
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p in nuxtApp.vueApp) {
|
|
||||||
return nuxtApp.vueApp[p]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p in nuxtApp) {
|
|
||||||
return nuxtApp[p]
|
|
||||||
}
|
|
||||||
|
|
||||||
return mock(`Accessing ${p} is not supported in Nuxt3.`)
|
|
||||||
}
|
|
||||||
}) as unknown as LegacyContext
|
|
||||||
|
|
||||||
if (process.client) {
|
|
||||||
nuxtApp.hook('app:created', () => {
|
|
||||||
const legacyApp = new Proxy(nuxtApp.vueApp as LegacyApp, {
|
|
||||||
get (source, p: keyof LegacyApp) {
|
|
||||||
// TODO: https://github.com/nuxt/framework/issues/244
|
|
||||||
if (['$root', 'constructor'].includes(p)) {
|
|
||||||
return legacyApp
|
|
||||||
}
|
|
||||||
return source[p] || nuxtApp[p]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
window[`$${nuxtApp.globalName}`] = legacyApp
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +1,18 @@
|
|||||||
import { defineComponent, getCurrentInstance, reactive, toRefs } from 'vue'
|
import { defineComponent, getCurrentInstance, reactive, toRefs } from 'vue'
|
||||||
import type { DefineComponent } from 'vue'
|
import type { DefineComponent } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import type { LegacyContext } from '../compat/legacy-app'
|
import { NuxtApp, useNuxtApp } from '../nuxt'
|
||||||
import { useNuxtApp } from '../nuxt'
|
|
||||||
import { useAsyncData } from './asyncData'
|
import { useAsyncData } from './asyncData'
|
||||||
|
|
||||||
export const NuxtComponentIndicator = '__nuxt_component'
|
export const NuxtComponentIndicator = '__nuxt_component'
|
||||||
|
|
||||||
async function runLegacyAsyncData (res: Record<string, any> | Promise<Record<string, any>>, fn: (context: LegacyContext) => Promise<Record<string, any>>) {
|
async function runLegacyAsyncData (res: Record<string, any> | Promise<Record<string, any>>, fn: (nuxtApp: NuxtApp) => Promise<Record<string, any>>) {
|
||||||
const nuxt = useNuxtApp()
|
const nuxt = useNuxtApp()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const vm = getCurrentInstance()
|
const vm = getCurrentInstance()
|
||||||
const { fetchKey } = vm.proxy.$options
|
const { fetchKey } = vm.proxy.$options
|
||||||
const key = typeof fetchKey === 'function' ? fetchKey(() => '') : fetchKey || route.fullPath
|
const key = typeof fetchKey === 'function' ? fetchKey(() => '') : fetchKey || route.fullPath
|
||||||
const { data } = await useAsyncData(`options:asyncdata:${key}`, () => fn(nuxt._legacyContext))
|
const { data } = await useAsyncData(`options:asyncdata:${key}`, () => fn(nuxt))
|
||||||
if (data.value && typeof data.value === 'object') {
|
if (data.value && typeof data.value === 'object') {
|
||||||
Object.assign(await res, toRefs(reactive(data.value)))
|
Object.assign(await res, toRefs(reactive(data.value)))
|
||||||
} else if (process.dev) {
|
} else if (process.dev) {
|
||||||
|
@ -6,7 +6,6 @@ import type { RuntimeConfig } from '@nuxt/schema'
|
|||||||
import { getContext } from 'unctx'
|
import { getContext } from 'unctx'
|
||||||
import type { SSRContext } from 'vue-bundle-renderer'
|
import type { SSRContext } from 'vue-bundle-renderer'
|
||||||
import type { CompatibilityEvent } from 'h3'
|
import type { CompatibilityEvent } from 'h3'
|
||||||
import { legacyPlugin, LegacyContext } from './compat/legacy-app'
|
|
||||||
|
|
||||||
const nuxtAppCtx = getContext<NuxtApp>('nuxt-app')
|
const nuxtAppCtx = getContext<NuxtApp>('nuxt-app')
|
||||||
|
|
||||||
@ -48,7 +47,6 @@ interface _NuxtApp {
|
|||||||
[key: string]: any
|
[key: string]: any
|
||||||
|
|
||||||
_asyncDataPromises?: Record<string, Promise<any>>
|
_asyncDataPromises?: Record<string, Promise<any>>
|
||||||
_legacyContext?: LegacyContext
|
|
||||||
|
|
||||||
ssrContext?: SSRContext & {
|
ssrContext?: SSRContext & {
|
||||||
url: string
|
url: string
|
||||||
@ -83,9 +81,6 @@ export interface Plugin<Injections extends Record<string, any> = Record<string,
|
|||||||
(nuxt: _NuxtApp): Promise<void> | Promise<{ provide?: Injections }> | void | { provide?: Injections }
|
(nuxt: _NuxtApp): Promise<void> | Promise<{ provide?: Injections }> | void | { provide?: Injections }
|
||||||
[NuxtPluginIndicator]?: true
|
[NuxtPluginIndicator]?: true
|
||||||
}
|
}
|
||||||
export interface LegacyPlugin {
|
|
||||||
(context: LegacyContext, provide: NuxtApp['provide']): Promise<void> | void
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CreateOptions {
|
export interface CreateOptions {
|
||||||
vueApp: NuxtApp['vueApp']
|
vueApp: NuxtApp['vueApp']
|
||||||
@ -185,24 +180,14 @@ export async function applyPlugins (nuxtApp: NuxtApp, plugins: Plugin[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function normalizePlugins (_plugins: Array<Plugin | LegacyPlugin>) {
|
export function normalizePlugins (_plugins: Plugin[]) {
|
||||||
let needsLegacyContext = false
|
|
||||||
|
|
||||||
const plugins = _plugins.map((plugin) => {
|
const plugins = _plugins.map((plugin) => {
|
||||||
if (typeof plugin !== 'function') {
|
if (typeof plugin !== 'function') {
|
||||||
return () => {}
|
return () => {}
|
||||||
}
|
}
|
||||||
if (isLegacyPlugin(plugin)) {
|
|
||||||
needsLegacyContext = true
|
|
||||||
return (nuxtApp: NuxtApp) => plugin(nuxtApp._legacyContext!, nuxtApp.provide)
|
|
||||||
}
|
|
||||||
return plugin
|
return plugin
|
||||||
})
|
})
|
||||||
|
|
||||||
if (needsLegacyContext) {
|
|
||||||
plugins.unshift(legacyPlugin)
|
|
||||||
}
|
|
||||||
|
|
||||||
return plugins as Plugin[]
|
return plugins as Plugin[]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,10 +196,6 @@ export function defineNuxtPlugin<T> (plugin: Plugin<T>) {
|
|||||||
return plugin
|
return plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isLegacyPlugin (plugin: unknown): plugin is LegacyPlugin {
|
|
||||||
return !plugin[NuxtPluginIndicator]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures that the setup function passed in has access to the Nuxt instance via `useNuxt`.
|
* Ensures that the setup function passed in has access to the Nuxt instance via `useNuxt`.
|
||||||
*
|
*
|
||||||
|
@ -27,6 +27,7 @@ export const componentsPluginTemplate = {
|
|||||||
filename: 'components.plugin.mjs',
|
filename: 'components.plugin.mjs',
|
||||||
getContents ({ options }: { options: ComponentsTemplateOptions }) {
|
getContents ({ options }: { options: ComponentsTemplateOptions }) {
|
||||||
return `import { defineAsyncComponent } from 'vue'
|
return `import { defineAsyncComponent } from 'vue'
|
||||||
|
import { defineNuxtPlugin } from '#app'
|
||||||
|
|
||||||
const components = ${genObjectFromRawEntries(options.components.filter(c => c.global === true).map((c) => {
|
const components = ${genObjectFromRawEntries(options.components.filter(c => c.global === true).map((c) => {
|
||||||
const exp = c.export === 'default' ? 'c.default || c' : `c['${c.export}']`
|
const exp = c.export === 'default' ? 'c.default || c' : `c['${c.export}']`
|
||||||
@ -35,12 +36,12 @@ const components = ${genObjectFromRawEntries(options.components.filter(c => c.gl
|
|||||||
return [c.pascalName, `defineAsyncComponent(${genDynamicImport(c.filePath, { comment })}.then(c => ${exp}))`]
|
return [c.pascalName, `defineAsyncComponent(${genDynamicImport(c.filePath, { comment })}.then(c => ${exp}))`]
|
||||||
}))}
|
}))}
|
||||||
|
|
||||||
export default function (nuxtApp) {
|
export default defineNuxtPlugin(nuxtApp => {
|
||||||
for (const name in components) {
|
for (const name in components) {
|
||||||
nuxtApp.vueApp.component(name, components[name])
|
nuxtApp.vueApp.component(name, components[name])
|
||||||
nuxtApp.vueApp.component('Lazy' + name, components[name])
|
nuxtApp.vueApp.component('Lazy' + name, components[name])
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,6 @@ export default {
|
|||||||
* Externalize `vue`, `@vue/*` and `vue-router` when build
|
* Externalize `vue`, `@vue/*` and `vue-router` when build
|
||||||
* @see https://github.com/nuxt/framework/issues/4084
|
* @see https://github.com/nuxt/framework/issues/4084
|
||||||
*/
|
*/
|
||||||
externalVue: false
|
externalVue: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user