From 8353e4c66eaae7d390c67e03c6217060786aef27 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 1 May 2023 17:35:00 +0100 Subject: [PATCH] feat(nuxt): allow access to components within app (#20604) --- packages/nuxt/src/components/module.ts | 11 ++++++----- packages/nuxt/src/components/templates.ts | 19 ++++++++++--------- packages/nuxt/src/core/app.ts | 1 + packages/schema/src/types/nuxt.ts | 2 ++ 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/packages/nuxt/src/components/module.ts b/packages/nuxt/src/components/module.ts index 5372d5faa4..4882bfc961 100644 --- a/packages/nuxt/src/components/module.ts +++ b/packages/nuxt/src/components/module.ts @@ -113,14 +113,14 @@ export default defineNuxtModule({ }) // components.d.ts - addTemplate({ ...componentsTypeTemplate, options: { getComponents } }) + addTemplate({ ...componentsTypeTemplate }) // components.plugin.mjs - addPluginTemplate({ ...componentsPluginTemplate, options: { getComponents } } as any) + addPluginTemplate({ ...componentsPluginTemplate } as any) // component-names.mjs - addTemplate({ ...componentNamesTemplate, options: { getComponents, mode: 'all' } }) + addTemplate({ ...componentNamesTemplate, options: { mode: 'all' } }) // components.islands.mjs if (nuxt.options.experimental.componentIslands) { - addTemplate({ ...componentsIslandsTemplate, filename: 'components.islands.mjs', options: { getComponents } }) + addTemplate({ ...componentsIslandsTemplate, filename: 'components.islands.mjs' }) } else { addTemplate({ filename: 'components.islands.mjs', getContents: () => 'export default {}' }) } @@ -158,7 +158,7 @@ export default defineNuxtModule({ }) // Scan components and add to plugin - nuxt.hook('app:templates', async () => { + nuxt.hook('app:templates', async (app) => { const newComponents = await scanComponents(componentDirs, nuxt.options.srcDir!) await nuxt.callHook('components:extend', newComponents) // add server placeholder for .client components server side. issue: #7085 @@ -173,6 +173,7 @@ export default defineNuxtModule({ } } context.components = newComponents + app.components = newComponents }) nuxt.hook('prepare:types', ({ references, tsConfig }) => { diff --git a/packages/nuxt/src/components/templates.ts b/packages/nuxt/src/components/templates.ts index b91ba871c6..fa2c7eb6d1 100644 --- a/packages/nuxt/src/components/templates.ts +++ b/packages/nuxt/src/components/templates.ts @@ -1,8 +1,9 @@ import { isAbsolute, relative } from 'pathe' import { genDynamicImport } from 'knitwork' -import type { Component, Nuxt, NuxtPluginTemplate, NuxtTemplate } from 'nuxt/schema' +import type { Component, Nuxt, NuxtApp, NuxtPluginTemplate, NuxtTemplate } from 'nuxt/schema' export interface ComponentsTemplateContext { + app: NuxtApp nuxt: Nuxt options: { getComponents: (mode?: 'client' | 'server' | 'all') => Component[] @@ -34,8 +35,8 @@ export default defineNuxtPlugin({ export const componentsPluginTemplate: NuxtPluginTemplate = { filename: 'components.plugin.mjs', - getContents ({ options }) { - const globalComponents = options.getComponents().filter(c => c.global) + getContents ({ app }) { + const globalComponents = app.components.filter(c => c.global) if (!globalComponents.length) { return emptyComponentsPlugin } return `import { defineNuxtPlugin } from '#app/nuxt' @@ -59,15 +60,15 @@ export default defineNuxtPlugin({ export const componentNamesTemplate: NuxtPluginTemplate = { filename: 'component-names.mjs', - getContents ({ options }) { - return `export const componentNames = ${JSON.stringify(options.getComponents().filter(c => !c.island).map(c => c.pascalName))}` + getContents ({ app }) { + return `export const componentNames = ${JSON.stringify(app.components.filter(c => !c.island).map(c => c.pascalName))}` } } export const componentsIslandsTemplate: NuxtTemplate = { // components.islands.mjs' - getContents ({ options }) { - const components = options.getComponents() + getContents ({ app }) { + const components = app.components const islands = components.filter(component => component.island || // .server components without a corresponding .client component will need to be rendered as an island @@ -85,9 +86,9 @@ export const componentsIslandsTemplate: NuxtTemplate export const componentsTypeTemplate: NuxtTemplate = { filename: 'components.d.ts', - getContents: ({ options, nuxt }) => { + getContents: ({ app, nuxt }) => { const buildDir = nuxt.options.buildDir - const componentTypes = options.getComponents().filter(c => !c.island).map(c => [ + const componentTypes = app.components.filter(c => !c.island).map(c => [ c.pascalName, `typeof ${genDynamicImport(isAbsolute(c.filePath) ? relative(buildDir, c.filePath).replace(/(?<=\w)\.(?!vue)\w+$/g, '') diff --git a/packages/nuxt/src/core/app.ts b/packages/nuxt/src/core/app.ts index e20b5da32f..38bef2b1cc 100644 --- a/packages/nuxt/src/core/app.ts +++ b/packages/nuxt/src/core/app.ts @@ -12,6 +12,7 @@ export function createApp (nuxt: Nuxt, options: Partial = {}): NuxtApp dir: nuxt.options.srcDir, extensions: nuxt.options.extensions, plugins: [], + components: [], templates: [] } as unknown as NuxtApp) as NuxtApp } diff --git a/packages/schema/src/types/nuxt.ts b/packages/schema/src/types/nuxt.ts index 85e40e3678..9e6de78335 100644 --- a/packages/schema/src/types/nuxt.ts +++ b/packages/schema/src/types/nuxt.ts @@ -1,6 +1,7 @@ import type { Hookable } from 'hookable' import type { Ignore } from 'ignore' import type { NuxtHooks, NuxtLayout, NuxtMiddleware } from './hooks' +import type { Component } from './components' import type { NuxtOptions } from './config' export interface Nuxt { @@ -58,6 +59,7 @@ export interface NuxtApp { dir: string extensions: string[] plugins: NuxtPlugin[] + components: Component[] layouts: Record middleware: NuxtMiddleware[] templates: NuxtTemplate[]