feat(nuxt): allow access to components within app (#20604)

This commit is contained in:
Daniel Roe 2023-05-01 17:35:00 +01:00 committed by GitHub
parent ecb2fda113
commit 8353e4c66e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 19 additions and 14 deletions

View File

@ -113,14 +113,14 @@ export default defineNuxtModule<ComponentsOptions>({
})
// 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<ComponentsOptions>({
})
// 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<ComponentsOptions>({
}
}
context.components = newComponents
app.components = newComponents
})
nuxt.hook('prepare:types', ({ references, tsConfig }) => {

View File

@ -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<ComponentsTemplateContext> = {
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<ComponentsTemplateContext> = {
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<ComponentsTemplateContext> = {
// 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<ComponentsTemplateContext>
export const componentsTypeTemplate: NuxtTemplate<ComponentsTemplateContext> = {
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, '')

View File

@ -12,6 +12,7 @@ export function createApp (nuxt: Nuxt, options: Partial<NuxtApp> = {}): NuxtApp
dir: nuxt.options.srcDir,
extensions: nuxt.options.extensions,
plugins: [],
components: [],
templates: []
} as unknown as NuxtApp) as NuxtApp
}

View File

@ -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<string, NuxtLayout>
middleware: NuxtMiddleware[]
templates: NuxtTemplate[]