From 2011e6c15917fbe3fa9f30dc2d9cdb9fa75a1378 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 31 Oct 2023 01:55:40 +0900 Subject: [PATCH 1/8] perf(nuxt): set `pages` on nuxt app and deduplicate calls (#24032) --- packages/nuxt/src/pages/module.ts | 25 ++++++++++++++----------- packages/schema/src/types/nuxt.ts | 3 ++- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/packages/nuxt/src/pages/module.ts b/packages/nuxt/src/pages/module.ts index b7e40e2e18..226c68753c 100644 --- a/packages/nuxt/src/pages/module.ts +++ b/packages/nuxt/src/pages/module.ts @@ -53,6 +53,11 @@ export default defineNuxtModule({ } nuxt.options.pages = await isPagesEnabled() + nuxt.hook('app:templates', async (app) => { + app.pages = await resolvePagesRoutes() + await nuxt.callHook('pages:extend', app.pages) + }) + // Restart Nuxt when pages dir is added or removed const restartPaths = nuxt.options._layers.flatMap((layer) => { const pagesDir = (layer.config.rootDir === nuxt.options.rootDir ? nuxt.options : layer.config).dir?.pages || 'pages' @@ -110,8 +115,11 @@ export default defineNuxtModule({ logs: nuxt.options.debug, async beforeWriteFiles (rootPage) { rootPage.children.forEach(child => child.delete()) - const pages = await resolvePagesRoutes() - await nuxt.callHook('pages:extend', pages) + let pages = nuxt.apps.default?.pages + if (!pages) { + pages = await resolvePagesRoutes() + await nuxt.callHook('pages:extend', pages) + } function addPage (parent: EditableTreeNode, page: NuxtPage) { // @ts-expect-error TODO: either fix types upstream or figure out another // way to add a route without a file, which must be possible @@ -339,12 +347,9 @@ export default defineNuxtModule({ ) // Do not prefetch page chunks - nuxt.hook('build:manifest', async (manifest) => { + nuxt.hook('build:manifest', (manifest) => { if (nuxt.options.dev) { return } - const pages = await resolvePagesRoutes() - await nuxt.callHook('pages:extend', pages) - - const sourceFiles = getSources(pages) + const sourceFiles = getSources(nuxt.apps.default.pages || []) for (const key in manifest) { if (manifest[key].isEntry) { @@ -357,10 +362,8 @@ export default defineNuxtModule({ // Add routes template addTemplate({ filename: 'routes.mjs', - async getContents () { - const pages = await resolvePagesRoutes() - await nuxt.callHook('pages:extend', pages) - const { routes, imports } = normalizeRoutes(pages) + getContents ({ app }) { + const { routes, imports } = normalizeRoutes(app.pages) return [...imports, `export default ${routes}`].join('\n') } }) diff --git a/packages/schema/src/types/nuxt.ts b/packages/schema/src/types/nuxt.ts index a55c0ed8de..ac1ad593a5 100644 --- a/packages/schema/src/types/nuxt.ts +++ b/packages/schema/src/types/nuxt.ts @@ -1,6 +1,6 @@ import type { Hookable } from 'hookable' import type { Ignore } from 'ignore' -import type { NuxtHooks, NuxtLayout, NuxtMiddleware } from './hooks' +import type { NuxtHooks, NuxtLayout, NuxtMiddleware, NuxtPage } from './hooks' import type { Component } from './components' import type { NuxtOptions } from './config' @@ -61,6 +61,7 @@ export interface NuxtApp { middleware: NuxtMiddleware[] templates: NuxtTemplate[] configs: string[] + pages?: NuxtPage[] } export interface Nuxt { From e297368ee3f994d2b73475834cb1ddcbe79db41d Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 30 Oct 2023 21:50:56 +0100 Subject: [PATCH 2/8] chore: revert pnpm upgrade --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bea11e1592..18819a70de 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "vue-router": "4.2.5", "vue-tsc": "1.8.22" }, - "packageManager": "pnpm@8.10.0", + "packageManager": "pnpm@8.9.2", "engines": { "node": "^14.18.0 || >=16.10.0" } From 62b7917d2ca21794a54e69b9667b1ac8547b2ed3 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 30 Oct 2023 21:56:34 +0100 Subject: [PATCH 3/8] fix(nuxt): use payload url for isPrerendered, not current route (#24031) --- packages/nuxt/src/app/composables/payload.ts | 8 +- packages/nuxt/src/core/nitro.ts | 98 +++++++++++--------- 2 files changed, 55 insertions(+), 51 deletions(-) diff --git a/packages/nuxt/src/app/composables/payload.ts b/packages/nuxt/src/app/composables/payload.ts index 7220a36e53..886ba3958b 100644 --- a/packages/nuxt/src/app/composables/payload.ts +++ b/packages/nuxt/src/app/composables/payload.ts @@ -23,7 +23,7 @@ export function loadPayload (url: string, opts: LoadPayloadOptions = {}): Record if (payloadURL in cache) { return cache[payloadURL] } - cache[payloadURL] = isPrerendered().then((prerendered) => { + cache[payloadURL] = isPrerendered(url).then((prerendered) => { if (!prerendered) { cache[payloadURL] = null return null @@ -78,11 +78,7 @@ async function _importPayload (payloadURL: string) { export async function isPrerendered (url = useRoute().path) { // Note: Alternative for server is checking x-nitro-prerender header - const nuxtApp = useNuxtApp() - if (nuxtApp.payload.prerenderedAt) { - return true - } - if (!appManifest) { return false } + if (!appManifest) { return !!useNuxtApp().payload.prerenderedAt } const manifest = await getAppManifest() if (manifest.prerendered.includes(url)) { return true diff --git a/packages/nuxt/src/core/nitro.ts b/packages/nuxt/src/core/nitro.ts index c51c829c48..46613fee20 100644 --- a/packages/nuxt/src/core/nitro.ts +++ b/packages/nuxt/src/core/nitro.ts @@ -244,53 +244,55 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) { } ) - nuxt.hook('nitro:build:before', async (nitro) => { - const routeRules = {} as Record - const _routeRules = nitro.options.routeRules - for (const key in _routeRules) { - if (key === '/__nuxt_error') { continue } - const filteredRules = Object.entries(_routeRules[key]) - .filter(([key, value]) => ['prerender', 'redirect'].includes(key) && value) - .map(([key, value]: any) => { - if (key === 'redirect') { - return [key, typeof value === 'string' ? value : value.to] - } - return [key, value] - }) - if (filteredRules.length > 0) { - routeRules[key] = Object.fromEntries(filteredRules) - } - } - - // Add pages prerendered but not covered by route rules - const prerenderedRoutes = new Set() - const routeRulesMatcher = toRouteMatcher( - createRadixRouter({ routes: routeRules }) - ) - const payloadSuffix = nuxt.options.experimental.renderJsonPayloads ? '/_payload.json' : '/_payload.js' - for (const route of nitro._prerenderedRoutes || []) { - if (!route.error && route.route.endsWith(payloadSuffix)) { - const url = route.route.slice(0, -payloadSuffix.length) || '/' - const rules = defu({}, ...routeRulesMatcher.matchAll(url).reverse()) as Record - if (!rules.prerender) { - prerenderedRoutes.add(url) + nuxt.hook('nitro:init', (nitro) => { + nitro.hooks.hook('rollup:before', async (nitro) => { + const routeRules = {} as Record + const _routeRules = nitro.options.routeRules + for (const key in _routeRules) { + if (key === '/__nuxt_error') { continue } + const filteredRules = Object.entries(_routeRules[key]) + .filter(([key, value]) => ['prerender', 'redirect'].includes(key) && value) + .map(([key, value]: any) => { + if (key === 'redirect') { + return [key, typeof value === 'string' ? value : value.to] + } + return [key, value] + }) + if (filteredRules.length > 0) { + routeRules[key] = Object.fromEntries(filteredRules) } } - } - const manifest = { - id: buildId, - timestamp: buildTimestamp, - matcher: exportMatcher(routeRulesMatcher), - prerendered: nuxt.options.dev ? [] : [...prerenderedRoutes] - } + // Add pages prerendered but not covered by route rules + const prerenderedRoutes = new Set() + const routeRulesMatcher = toRouteMatcher( + createRadixRouter({ routes: routeRules }) + ) + const payloadSuffix = nuxt.options.experimental.renderJsonPayloads ? '/_payload.json' : '/_payload.js' + for (const route of nitro._prerenderedRoutes || []) { + if (!route.error && route.route.endsWith(payloadSuffix)) { + const url = route.route.slice(0, -payloadSuffix.length) || '/' + const rules = defu({}, ...routeRulesMatcher.matchAll(url).reverse()) as Record + if (!rules.prerender) { + prerenderedRoutes.add(url) + } + } + } - await fsp.mkdir(join(tempDir, 'meta'), { recursive: true }) - await fsp.writeFile(join(tempDir, 'latest.json'), JSON.stringify({ - id: buildId, - timestamp: buildTimestamp - })) - await fsp.writeFile(join(tempDir, `meta/${buildId}.json`), JSON.stringify(manifest)) + const manifest = { + id: buildId, + timestamp: buildTimestamp, + matcher: exportMatcher(routeRulesMatcher), + prerendered: nuxt.options.dev ? [] : [...prerenderedRoutes] + } + + await fsp.mkdir(join(tempDir, 'meta'), { recursive: true }) + await fsp.writeFile(join(tempDir, 'latest.json'), JSON.stringify({ + id: buildId, + timestamp: buildTimestamp + })) + await fsp.writeFile(join(tempDir, `meta/${buildId}.json`), JSON.stringify(manifest)) + }) }) } @@ -457,6 +459,14 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) { }) } + // Copy public assets after prerender so app manifest can be present + if (!nuxt.options.dev) { + nitro.hooks.hook('rollup:before', async (nitro) => { + await copyPublicAssets(nitro) + await nuxt.callHook('nitro:build:public-assets', nitro) + }) + } + // nuxt build/dev nuxt.hook('build:done', async () => { await nuxt.callHook('nitro:build:before', nitro) @@ -464,8 +474,6 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) { await build(nitro) } else { await prepare(nitro) - await copyPublicAssets(nitro) - await nuxt.callHook('nitro:build:public-assets', nitro) await prerender(nitro) logger.restoreAll() From 4f017a5538d1c17864fca5723c5021f13cd9723f Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 30 Oct 2023 22:02:41 +0100 Subject: [PATCH 4/8] fix(vite): don't warm up css deps and normalise urls correctly (#23975) --- packages/vite/src/utils/warmup.ts | 42 ++++++++++++++++++++++++++++--- packages/vite/src/vite.ts | 8 ++---- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/packages/vite/src/utils/warmup.ts b/packages/vite/src/utils/warmup.ts index ac98838a82..7543460a32 100644 --- a/packages/vite/src/utils/warmup.ts +++ b/packages/vite/src/utils/warmup.ts @@ -1,6 +1,33 @@ import { logger } from '@nuxt/kit' +import { join, normalize, relative } from 'pathe' +import { withoutBase } from 'ufo' +import { isCSSRequest } from 'vite' import type { ViteDevServer } from 'vite' +// https://github.com/vitejs/vite/tree/main/packages/vite/src/node/server/warmup.ts#L62-L70 +function fileToUrl (file: string, root: string) { + const url = relative(root, file) + // out of root, use /@fs/ prefix + if (url[0] === '.') { + return join('/@fs/', normalize(file)) + } + // file within root, create root-relative url + return '/' + normalize(url) +} + +function normaliseURL (url: string, base: string) { + // remove any base url + url = withoutBase(url, base) + // unwrap record + if (url.startsWith('/@id/')) { + url = url.slice('/@id/'.length).replace('__x00__', '\0') + } + // strip query + url = url.replace(/(\?|&)import=?(?:&|$)/, '').replace(/[?&]$/, '') + return url +} + +// TODO: use built-in warmup logic when we update to vite 5 export async function warmupViteServer ( server: ViteDevServer, entries: string[], @@ -9,7 +36,12 @@ export async function warmupViteServer ( const warmedUrls = new Set() const warmup = async (url: string) => { - if (warmedUrls.has(url)) { + url = normaliseURL(url, server.config.base) + + if (warmedUrls.has(url)) { return } + const m = await server.moduleGraph.getModuleByUrl(url, isServer) + // a module that is already compiled (and can't be warmed up anyway) + if (m?.transformResult?.code || m?.ssrTransformResult?.code) { return } warmedUrls.add(url) @@ -18,10 +50,14 @@ export async function warmupViteServer ( } catch (e) { logger.debug('Warmup for %s failed with: %s', url, e) } + + // Don't warmup CSS file dependencies as they have already all been loaded to produce result + if (isCSSRequest(url)) { return } + const mod = await server.moduleGraph.getModuleByUrl(url, isServer) const deps = mod?.ssrTransformResult?.deps /* server */ || Array.from(mod?.importedModules /* client */ || []).map(m => m.url) - await Promise.all(deps.map(m => warmup(m.replace('/@id/__x00__', '\0')))) + await Promise.all(deps.map(m => warmup(m))) } - await Promise.all(entries.map(entry => warmup(entry))) + await Promise.all(entries.map(entry => warmup(fileToUrl(entry, server.config.root)))) } diff --git a/packages/vite/src/vite.ts b/packages/vite/src/vite.ts index 962c36f9c7..62d850872a 100644 --- a/packages/vite/src/vite.ts +++ b/packages/vite/src/vite.ts @@ -192,13 +192,9 @@ export const bundle: NuxtBuilder['bundle'] = async (nuxt) => { } }) - if ( - nuxt.options.vite.warmupEntry !== false && - // https://github.com/nuxt/nuxt/issues/14898 - !(env.isServer && ctx.nuxt.options.vite.devBundler !== 'legacy') - ) { + if (nuxt.options.vite.warmupEntry !== false) { const start = Date.now() - warmupViteServer(server, [join('/@fs/', ctx.entry)], env.isServer) + warmupViteServer(server, [ctx.entry], env.isServer) .then(() => logger.info(`Vite ${env.isClient ? 'client' : 'server'} warmed up in ${Date.now() - start}ms`)) .catch(logger.error) } From 27791f4c3350e2baa1a55c7be71bfbc02a7662b5 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 30 Oct 2023 22:04:45 +0100 Subject: [PATCH 5/8] perf(nuxt): remove pure annotations plugin (#24033) --- .../nuxt/src/app/components/nuxt-root.vue | 2 +- packages/nuxt/src/components/loader.ts | 4 +- .../components/runtime/server-component.ts | 1 + packages/nuxt/src/components/templates.ts | 2 +- .../nuxt/src/pages/runtime/composables.ts | 1 + packages/vite/src/client.ts | 7 +--- packages/vite/src/plugins/pure-annotations.ts | 40 ------------------- packages/vite/src/server.ts | 8 +--- 8 files changed, 8 insertions(+), 57 deletions(-) delete mode 100644 packages/vite/src/plugins/pure-annotations.ts diff --git a/packages/nuxt/src/app/components/nuxt-root.vue b/packages/nuxt/src/app/components/nuxt-root.vue index 80a9d38ac1..378c8ee59c 100644 --- a/packages/nuxt/src/app/components/nuxt-root.vue +++ b/packages/nuxt/src/app/components/nuxt-root.vue @@ -24,7 +24,7 @@ const nuxtApp = useNuxtApp() const onResolve = nuxtApp.deferHydration() const url = import.meta.server ? nuxtApp.ssrContext.url : window.location.pathname -const SingleRenderer = import.meta.test && import.meta.dev && import.meta.server && url.startsWith('/__nuxt_component_test__/') && /* #__PURE__ */ defineAsyncComponent(() => import('#build/test-component-wrapper.mjs') +const SingleRenderer = import.meta.test && import.meta.dev && import.meta.server && url.startsWith('/__nuxt_component_test__/') && defineAsyncComponent(() => import('#build/test-component-wrapper.mjs') .then(r => r.default(import.meta.server ? url : window.location.href))) // Inject default route (outside of pages) as active route diff --git a/packages/nuxt/src/components/loader.ts b/packages/nuxt/src/components/loader.ts index 5e42223bb3..d219705462 100644 --- a/packages/nuxt/src/components/loader.ts +++ b/packages/nuxt/src/components/loader.ts @@ -74,12 +74,12 @@ export const loaderPlugin = createUnplugin((options: LoaderOptions) => { if (lazy) { imports.add(genImport('vue', [{ name: 'defineAsyncComponent', as: '__defineAsyncComponent' }])) identifier += '_lazy' - imports.add(`const ${identifier} = /*#__PURE__*/ __defineAsyncComponent(${genDynamicImport(component.filePath, { interopDefault: true })}${isClientOnly ? '.then(c => createClientOnly(c))' : ''})`) + imports.add(`const ${identifier} = __defineAsyncComponent(${genDynamicImport(component.filePath, { interopDefault: true })}${isClientOnly ? '.then(c => createClientOnly(c))' : ''})`) } else { imports.add(genImport(component.filePath, [{ name: component.export, as: identifier }])) if (isClientOnly) { - imports.add(`const ${identifier}_wrapped = /*#__PURE__*/ createClientOnly(${identifier})`) + imports.add(`const ${identifier}_wrapped = createClientOnly(${identifier})`) identifier += '_wrapped' } } diff --git a/packages/nuxt/src/components/runtime/server-component.ts b/packages/nuxt/src/components/runtime/server-component.ts index b8d7e216a3..e1f75e6a59 100644 --- a/packages/nuxt/src/components/runtime/server-component.ts +++ b/packages/nuxt/src/components/runtime/server-component.ts @@ -1,6 +1,7 @@ import { defineComponent, h } from 'vue' import NuxtIsland from '#app/components/nuxt-island' +/*! @__NO_SIDE_EFFECTS__ */ export const createServerComponent = (name: string) => { return defineComponent({ name, diff --git a/packages/nuxt/src/components/templates.ts b/packages/nuxt/src/components/templates.ts index 2847270a33..d0e250c5a7 100644 --- a/packages/nuxt/src/components/templates.ts +++ b/packages/nuxt/src/components/templates.ts @@ -90,7 +90,7 @@ export const componentsIslandsTemplate: NuxtTemplate (c) => { const exp = c.export === 'default' ? 'c.default || c' : `c['${c.export}']` const comment = createImportMagicComments(c) - return `export const ${c.pascalName} = /* #__PURE__ */ defineAsyncComponent(${genDynamicImport(c.filePath, { comment })}.then(c => ${exp}))` + return `export const ${c.pascalName} = defineAsyncComponent(${genDynamicImport(c.filePath, { comment })}.then(c => ${exp}))` } )].join('\n') } diff --git a/packages/nuxt/src/pages/runtime/composables.ts b/packages/nuxt/src/pages/runtime/composables.ts index 24714cd252..3b1ee9210c 100644 --- a/packages/nuxt/src/pages/runtime/composables.ts +++ b/packages/nuxt/src/pages/runtime/composables.ts @@ -76,5 +76,6 @@ export const definePageMeta = (meta: PageMeta): void => { * For more control, such as if you are using a custom `path` or `alias` set in the page's `definePageMeta`, you * should set `routeRules` directly within your `nuxt.config`. */ +/*! @__NO_SIDE_EFFECTS__ */ // eslint-disable-next-line @typescript-eslint/no-unused-vars export const defineRouteRules = (rules: NitroRouteConfig): void => {} diff --git a/packages/vite/src/client.ts b/packages/vite/src/client.ts index a8dca717fa..171f314cff 100644 --- a/packages/vite/src/client.ts +++ b/packages/vite/src/client.ts @@ -15,7 +15,6 @@ import type { ViteBuildContext } from './vite' import { devStyleSSRPlugin } from './plugins/dev-ssr-css' import { runtimePathsPlugin } from './plugins/paths' import { typeCheckPlugin } from './plugins/type-check' -import { pureAnnotationsPlugin } from './plugins/pure-annotations' import { viteNodePlugin } from './vite-node' import { createViteLogger } from './utils/logger' @@ -80,11 +79,7 @@ export async function buildClient (ctx: ViteBuildContext) { runtimePathsPlugin({ sourcemap: !!ctx.nuxt.options.sourcemap.client }), - viteNodePlugin(ctx), - pureAnnotationsPlugin.vite({ - sourcemap: !!ctx.nuxt.options.sourcemap.client, - functions: ['defineComponent', 'defineAsyncComponent', 'defineNuxtLink', 'createClientOnly', 'defineNuxtPlugin', 'defineNuxtRouteMiddleware', 'defineNuxtComponent', 'useRuntimeConfig', 'defineRouteRules'] - }) + viteNodePlugin(ctx) ], appType: 'custom', server: { diff --git a/packages/vite/src/plugins/pure-annotations.ts b/packages/vite/src/plugins/pure-annotations.ts deleted file mode 100644 index 9154f54863..0000000000 --- a/packages/vite/src/plugins/pure-annotations.ts +++ /dev/null @@ -1,40 +0,0 @@ -import MagicString from 'magic-string' -import { createUnplugin } from 'unplugin' -import { stripLiteral } from 'strip-literal' -import { isJS, isVue } from '../../../nuxt/src/core/utils/plugins' - -interface PureAnnotationsOptions { - sourcemap: boolean - functions: string[] -} - -export const pureAnnotationsPlugin = createUnplugin((options: PureAnnotationsOptions) => { - const FUNCTION_RE = new RegExp(`(? Date: Mon, 30 Oct 2023 22:05:02 +0100 Subject: [PATCH 6/8] perf(nuxt): use granular imports for auto-importing composables (#23951) --- .eslintrc | 5 + docs/3.api/5.kit/10.templates.md | 2 +- docs/3.api/5.kit/9.plugins.md | 2 +- .../src/app/components/island-renderer.ts | 3 +- .../src/app/components/nuxt-error-boundary.ts | 2 +- .../nuxt/src/app/components/nuxt-island.ts | 4 +- .../nuxt/src/app/components/nuxt-layout.ts | 9 +- .../app/components/nuxt-loading-indicator.ts | 4 +- .../nuxt/src/app/components/nuxt-root.vue | 8 +- .../nuxt/src/app/components/route-provider.ts | 2 +- packages/nuxt/src/app/composables/chunk.ts | 2 +- packages/nuxt/src/app/composables/hydrate.ts | 2 +- packages/nuxt/src/app/composables/manifest.ts | 2 +- packages/nuxt/src/app/composables/payload.ts | 4 +- packages/nuxt/src/app/composables/router.ts | 7 +- packages/nuxt/src/app/composables/url.ts | 2 +- packages/nuxt/src/app/entry.async.ts | 2 +- packages/nuxt/src/app/entry.ts | 4 +- packages/nuxt/src/app/index.ts | 2 + .../src/app/middleware/manifest-route-rule.ts | 4 +- packages/nuxt/src/app/nuxt.ts | 6 +- .../plugins/check-outdated-build.client.ts | 6 +- .../src/app/plugins/chunk-reload.client.ts | 6 +- .../plugins/cross-origin-prefetch.client.ts | 2 +- packages/nuxt/src/app/plugins/debug.ts | 2 +- .../nuxt/src/app/plugins/payload.client.ts | 10 +- .../nuxt/src/app/plugins/preload.server.ts | 2 +- .../src/app/plugins/restore-state.client.ts | 2 +- .../src/app/plugins/revive-payload.client.ts | 6 +- .../src/app/plugins/revive-payload.server.ts | 6 +- .../app/plugins/view-transitions.client.ts | 6 +- packages/nuxt/src/core/templates.ts | 2 +- .../nuxt/src/head/runtime/plugins/unhead.ts | 3 +- packages/nuxt/src/imports/presets.ts | 145 ++++++++++-------- packages/nuxt/src/pages/module.ts | 2 +- .../nuxt/src/pages/runtime/composables.ts | 2 +- .../nuxt/src/pages/runtime/plugins/router.ts | 5 +- packages/nuxt/test/auto-imports.test.ts | 2 +- 38 files changed, 161 insertions(+), 126 deletions(-) diff --git a/.eslintrc b/.eslintrc index 528bcc4a57..feb6e78660 100644 --- a/.eslintrc +++ b/.eslintrc @@ -70,6 +70,11 @@ "target": "packages/nuxt/src/app", "message": "app should not directly import from modules." }, + { + "from": "packages/nuxt/src/app/**/index.ts", + "target": "packages/nuxt/src", + "message": "should not import from barrel/index files" + }, { "from": "packages/nitro", "target": "packages/!(nitro)/**/*", diff --git a/docs/3.api/5.kit/10.templates.md b/docs/3.api/5.kit/10.templates.md index e02b76ff71..d748246942 100644 --- a/docs/3.api/5.kit/10.templates.md +++ b/docs/3.api/5.kit/10.templates.md @@ -112,7 +112,7 @@ export default defineNuxtModule({ ```ts [plugin.ts] import { createHead as createClientHead, createServerHead } from '@unhead/vue' -import { defineNuxtPlugin } from '#app' +import { defineNuxtPlugin } from '#imports' // @ts-ignore import metaConfig from '#build/meta.config.mjs' diff --git a/docs/3.api/5.kit/9.plugins.md b/docs/3.api/5.kit/9.plugins.md index da4940419d..483c516c1b 100644 --- a/docs/3.api/5.kit/9.plugins.md +++ b/docs/3.api/5.kit/9.plugins.md @@ -234,7 +234,7 @@ export default defineNuxtModule({ ```ts [runtime/plugin.ejs] import { VueFire, useSSRInitialState } from 'vuefire' -import { defineNuxtPlugin } from '#app' +import { defineNuxtPlugin } from '#imports' export default defineNuxtPlugin((nuxtApp) => { const firebaseApp = nuxtApp.$firebaseApp diff --git a/packages/nuxt/src/app/components/island-renderer.ts b/packages/nuxt/src/app/components/island-renderer.ts index 421e3863ab..62d83f1126 100644 --- a/packages/nuxt/src/app/components/island-renderer.ts +++ b/packages/nuxt/src/app/components/island-renderer.ts @@ -1,9 +1,10 @@ import type { defineAsyncComponent } from 'vue' import { createVNode, defineComponent } from 'vue' +import { createError } from '../composables/error' + // @ts-expect-error virtual file import * as islandComponents from '#build/components.islands.mjs' -import { createError } from '#app/composables/error' export default defineComponent({ props: { diff --git a/packages/nuxt/src/app/components/nuxt-error-boundary.ts b/packages/nuxt/src/app/components/nuxt-error-boundary.ts index cb8d2f6707..e038adab1a 100644 --- a/packages/nuxt/src/app/components/nuxt-error-boundary.ts +++ b/packages/nuxt/src/app/components/nuxt-error-boundary.ts @@ -1,5 +1,5 @@ import { defineComponent, onErrorCaptured, ref } from 'vue' -import { useNuxtApp } from '#app/nuxt' +import { useNuxtApp } from '../nuxt' export default defineComponent({ emits: { diff --git a/packages/nuxt/src/app/components/nuxt-island.ts b/packages/nuxt/src/app/components/nuxt-island.ts index 9ba2befc46..40162a15e3 100644 --- a/packages/nuxt/src/app/components/nuxt-island.ts +++ b/packages/nuxt/src/app/components/nuxt-island.ts @@ -9,9 +9,9 @@ import type { FetchResponse } from 'ofetch' // eslint-disable-next-line import/no-restricted-paths import type { NuxtIslandResponse } from '../../core/runtime/nitro/renderer' +import { useNuxtApp, useRuntimeConfig } from '../nuxt' +import { prerenderRoutes, useRequestEvent } from '../composables/ssr' import { getFragmentHTML, getSlotProps } from './utils' -import { useNuxtApp, useRuntimeConfig } from '#app/nuxt' -import { prerenderRoutes, useRequestEvent } from '#app/composables/ssr' // @ts-expect-error virtual file import { remoteComponentIslands } from '#build/nuxt.config.mjs' diff --git a/packages/nuxt/src/app/components/nuxt-layout.ts b/packages/nuxt/src/app/components/nuxt-layout.ts index 37cfa0d1e2..01a682dca2 100644 --- a/packages/nuxt/src/app/components/nuxt-layout.ts +++ b/packages/nuxt/src/app/components/nuxt-layout.ts @@ -1,12 +1,15 @@ import type { DefineComponent, MaybeRef, VNode } from 'vue' import { Suspense, Transition, computed, defineComponent, h, inject, mergeProps, nextTick, onMounted, provide, ref, unref } from 'vue' import type { RouteLocationNormalizedLoaded } from 'vue-router' + +// eslint-disable-next-line import/no-restricted-paths +import type { PageMeta } from '../../pages/runtime/composables' + +import { useRoute } from '../composables/router' +import { useNuxtApp } from '../nuxt' import { _wrapIf } from './utils' import { LayoutMetaSymbol, PageRouteSymbol } from './injections' -import type { PageMeta } from '#app' -import { useRoute } from '#app/composables/router' -import { useNuxtApp } from '#app/nuxt' // @ts-expect-error virtual file import { useRoute as useVueRouterRoute } from '#build/pages' // @ts-expect-error virtual file diff --git a/packages/nuxt/src/app/components/nuxt-loading-indicator.ts b/packages/nuxt/src/app/components/nuxt-loading-indicator.ts index bf5a11cbd3..01a58b5fd2 100644 --- a/packages/nuxt/src/app/components/nuxt-loading-indicator.ts +++ b/packages/nuxt/src/app/components/nuxt-loading-indicator.ts @@ -1,7 +1,7 @@ import { computed, defineComponent, h, onBeforeUnmount, ref } from 'vue' +import { useNuxtApp } from '../nuxt' +import { useRouter } from '../composables/router' import { isChangingPage } from './utils' -import { useNuxtApp } from '#app/nuxt' -import { useRouter } from '#app/composables/router' // @ts-expect-error virtual file import { globalMiddleware } from '#build/middleware' diff --git a/packages/nuxt/src/app/components/nuxt-root.vue b/packages/nuxt/src/app/components/nuxt-root.vue index 378c8ee59c..2d8501dcb7 100644 --- a/packages/nuxt/src/app/components/nuxt-root.vue +++ b/packages/nuxt/src/app/components/nuxt-root.vue @@ -9,10 +9,10 @@