From 2b176790aee1d609ca7eced63fef5c693283524c Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Fri, 22 Jul 2022 15:33:51 +0100 Subject: [PATCH 1/6] feat(nuxt): add support for global components via dir and suffix --- .../3.directory-structure/4.components.md | 6 +++ packages/nuxt/src/components/module.ts | 36 ++++++++----- packages/nuxt/src/components/scan.ts | 17 +++--- packages/nuxt/src/components/templates.ts | 54 ++++++++++++------- packages/schema/src/config/_adhoc.ts | 2 +- test/basic.test.ts | 2 + .../basic/components/WithSuffix.global.vue | 3 ++ .../basic/components/global/TestGlobal.vue | 3 ++ test/fixtures/basic/pages/index.vue | 2 + 9 files changed, 86 insertions(+), 39 deletions(-) create mode 100644 test/fixtures/basic/components/WithSuffix.global.vue create mode 100644 test/fixtures/basic/components/global/TestGlobal.vue diff --git a/docs/content/2.guide/3.directory-structure/4.components.md b/docs/content/2.guide/3.directory-structure/4.components.md index d344277d549..c2350d19f59 100644 --- a/docs/content/2.guide/3.directory-structure/4.components.md +++ b/docs/content/2.guide/3.directory-structure/4.components.md @@ -80,6 +80,12 @@ Alternatively, though not recommended, you can register all your components glob }) ``` +::StabilityEdge{title="Automatic global components"} +In the current version, components in `~/components/global` are not yet auto-registered. +:: + +You can also selectively register some components globally by placing them in a `~/components/global` directory. + ::alert{type=info} The `global` option can also be set per component directory. :: diff --git a/packages/nuxt/src/components/module.ts b/packages/nuxt/src/components/module.ts index 3f394b162c8..3f394d13dd4 100644 --- a/packages/nuxt/src/components/module.ts +++ b/packages/nuxt/src/components/module.ts @@ -13,6 +13,8 @@ function compareDirByPathLength ({ path: pathA }, { path: pathB }) { return pathB.split(/[\\/]/).filter(Boolean).length - pathA.split(/[\\/]/).filter(Boolean).length } +const DEFAULT_COMPONENTS_DIRS_RE = /^(components|global)$/ + export default defineNuxtModule({ meta: { name: 'components', @@ -30,7 +32,10 @@ export default defineNuxtModule({ return dir.map(dir => normalizeDirs(dir, cwd)).flat().sort(compareDirByPathLength) } if (dir === true || dir === undefined) { - return [{ path: resolve(cwd, 'components') }] + return [ + { path: resolve(cwd, 'components/global'), global: true }, + { path: resolve(cwd, 'components') } + ] } if (typeof dir === 'string') { return { @@ -65,7 +70,7 @@ export default defineNuxtModule({ dirOptions.level = Number(dirOptions.level || 0) const present = isDirectory(dirPath) - if (!present && basename(dirOptions.path) !== 'components') { + if (!present && !DEFAULT_COMPONENTS_DIRS_RE.test(basename(dirOptions.path))) { // eslint-disable-next-line no-console console.warn('Components directory not found: `' + dirPath + '`') } @@ -90,28 +95,35 @@ export default defineNuxtModule({ nuxt.options.build!.transpile!.push(...componentDirs.filter(dir => dir.transpile).map(dir => dir.path)) }) - const options = { components, buildDir: nuxt.options.buildDir } + const context = { components } addTemplate({ ...componentsTypeTemplate, - options + options: { context } }) addPluginTemplate({ ...componentsPluginTemplate, - options + options: { context } }) - nuxt.options.alias['#components'] = resolve(nuxt.options.buildDir, componentsTemplate.filename) - addTemplate({ - ...componentsTemplate, - options + nuxt.hook('vite:extendConfig', (config, { isClient }) => { + const mode = isClient ? 'client' : 'server' + config.resolve.alias['#components'] = resolve(nuxt.options.buildDir, `components.${mode}.mjs`) + }) + nuxt.hook('webpack:config', (configs) => { + for (const config of configs) { + const mode = config.name === 'server' ? 'server' : 'client' + config.resolve.alias['#components'] = resolve(nuxt.options.buildDir, `components.${mode}.mjs`) + } }) + addTemplate({ ...componentsTemplate, filename: 'components.server.mjs', options: { context, mode: 'server' } }) + addTemplate({ ...componentsTemplate, filename: 'components.client.mjs', options: { context, mode: 'client' } }) // Scan components and add to plugin nuxt.hook('app:templates', async () => { - options.components = await scanComponents(componentDirs, nuxt.options.srcDir!) - await nuxt.callHook('components:extend', options.components) + context.components = await scanComponents(componentDirs, nuxt.options.srcDir!) + await nuxt.callHook('components:extend', context.components) }) nuxt.hook('prepare:types', ({ references }) => { @@ -129,7 +141,7 @@ export default defineNuxtModule({ } }) - const getComponents = () => options.components + const getComponents = () => context.components nuxt.hook('vite:extendConfig', (config, { isClient }) => { config.plugins = config.plugins || [] config.plugins.push(loaderPlugin.vite({ diff --git a/packages/nuxt/src/components/scan.ts b/packages/nuxt/src/components/scan.ts index bb249435722..17a72b35d8f 100644 --- a/packages/nuxt/src/components/scan.ts +++ b/packages/nuxt/src/components/scan.ts @@ -61,8 +61,9 @@ export async function scanComponents (dirs: ComponentsDir[], srcDir: string): Pr */ let fileName = basename(filePath, extname(filePath)) - const mode = fileName.match(/(?<=\.)(client|server)$/)?.[0] as 'client' | 'server' || 'all' - fileName = fileName.replace(/\.(client|server)$/, '') + const global = /\.(global)$/.test(fileName) || dir.global + const mode = fileName.match(/(?<=\.)(client|server)(\.global)?$/)?.[1] as 'client' | 'server' || 'all' + fileName = fileName.replace(/(\.client|server)?(\.global)?$/, '') if (fileName.toLowerCase() === 'index') { fileName = dir.pathPrefix === false ? basename(dirname(filePath)) : '' /* inherits from path */ @@ -102,16 +103,18 @@ export async function scanComponents (dirs: ComponentsDir[], srcDir: string): Pr const chunkName = 'components/' + kebabName + suffix let component: Component = { + // inheritable from directory configuration + mode, + global, + prefetch: Boolean(dir.prefetch), + preload: Boolean(dir.preload), + // specific to the file filePath, pascalName, kebabName, chunkName, shortPath, - export: 'default', - global: dir.global, - prefetch: Boolean(dir.prefetch), - preload: Boolean(dir.preload), - mode + export: 'default' } if (typeof dir.extendComponent === 'function') { diff --git a/packages/nuxt/src/components/templates.ts b/packages/nuxt/src/components/templates.ts index 915697f82f6..1ad552a984b 100644 --- a/packages/nuxt/src/components/templates.ts +++ b/packages/nuxt/src/components/templates.ts @@ -1,11 +1,13 @@ import { isAbsolute, relative } from 'pathe' -import type { Component } from '@nuxt/schema' +import type { Component, Nuxt } from '@nuxt/schema' import { genDynamicImport, genExport, genObjectFromRawEntries } from 'knitwork' -import { upperFirst } from 'scule' -export type ComponentsTemplateOptions = { - buildDir?: string - components: Component[] +export interface ComponentsTemplateContext { + nuxt: Nuxt + options: { + context: { components: Component[] } + mode?: 'client' | 'server' + } } export type ImportMagicCommentsOptions = { @@ -25,11 +27,13 @@ const createImportMagicComments = (options: ImportMagicCommentsOptions) => { export const componentsPluginTemplate = { filename: 'components.plugin.mjs', - getContents ({ options }: { options: ComponentsTemplateOptions }) { + getContents ({ options }: ComponentsTemplateContext) { + const globalComponents = options.context.components.filter(c => c.global === true) + return `import { defineAsyncComponent } from 'vue' import { defineNuxtPlugin } from '#app' -const components = ${genObjectFromRawEntries(options.components.filter(c => c.global === true).map((c) => { +const components = ${genObjectFromRawEntries(globalComponents.map((c) => { const exp = c.export === 'default' ? 'c.default || c' : `c['${c.export}']` const comment = createImportMagicComments(c) @@ -47,36 +51,48 @@ export default defineNuxtPlugin(nuxtApp => { } export const componentsTemplate = { - filename: 'components.mjs', - getContents ({ options }: { options: ComponentsTemplateOptions }) { + getContents ({ options }: ComponentsTemplateContext) { + const components = options.context.components return [ 'import { defineAsyncComponent } from \'vue\'', - ...options.components.flatMap((c) => { + ...components.flatMap((c) => { const exp = c.export === 'default' ? 'c.default || c' : `c['${c.export}']` const comment = createImportMagicComments(c) - const nameWithSuffix = `${c.pascalName}${c.mode !== 'all' ? upperFirst(c.mode) : ''}` + + // Exclude client/server-only components from other build + if (c.mode !== 'all' && c.mode !== options.mode) { return [] } return [ - genExport(c.filePath, [{ name: c.export, as: nameWithSuffix }]), - `export const Lazy${nameWithSuffix} = defineAsyncComponent(${genDynamicImport(c.filePath, { comment })}.then(c => ${exp}))` + genExport(c.filePath, [{ name: c.export, as: c.pascalName }]), + `export const Lazy${c.pascalName} = defineAsyncComponent(${genDynamicImport(c.filePath, { comment })}.then(c => ${exp}))` ] }), - `export const componentNames = ${JSON.stringify(options.components.map(c => c.pascalName))}` + `export const componentNames = ${JSON.stringify(components.map(c => c.pascalName))}` ].join('\n') } } export const componentsTypeTemplate = { filename: 'components.d.ts', - getContents: ({ options }: { options: ComponentsTemplateOptions }) => `// Generated by components discovery + getContents: ({ options, nuxt }: ComponentsTemplateContext) => { + const buildDir = nuxt.options.buildDir + const componentTypes = options.context.components.map(c => [ + c.pascalName, + `typeof ${genDynamicImport(isAbsolute(c.filePath) ? relative(buildDir, c.filePath) : c.filePath, { wrapper: false })}['${c.export}']` + ]) + + return `// Generated by components discovery declare module 'vue' { export interface GlobalComponents { -${options.components.map(c => ` '${c.pascalName}': typeof ${genDynamicImport(isAbsolute(c.filePath) ? relative(options.buildDir, c.filePath) : c.filePath, { wrapper: false })}['${c.export}']`).join(',\n')} -${options.components.map(c => ` 'Lazy${c.pascalName}': typeof ${genDynamicImport(isAbsolute(c.filePath) ? relative(options.buildDir, c.filePath) : c.filePath, { wrapper: false })}['${c.export}']`).join(',\n')} +${componentTypes.map(([pascalName, type]) => ` '${pascalName}': ${type}`).join(',\n')} +${componentTypes.map(([pascalName, type]) => ` 'Lazy${pascalName}': ${type}`).join(',\n')} } } -${options.components.map(c => `export const ${c.pascalName}${c.mode !== 'all' ? upperFirst(c.mode) : ''}: typeof ${genDynamicImport(isAbsolute(c.filePath) ? relative(options.buildDir, c.filePath) : c.filePath, { wrapper: false })}['${c.export}']`).join('\n')} -${options.components.map(c => `export const Lazy${c.pascalName}${c.mode !== 'all' ? upperFirst(c.mode) : ''}: typeof ${genDynamicImport(isAbsolute(c.filePath) ? relative(options.buildDir, c.filePath) : c.filePath, { wrapper: false })}['${c.export}']`).join('\n')} + +${componentTypes.map(([pascalName, type]) => `export const ${pascalName}: ${type}`).join(',\n')} +${componentTypes.map(([pascalName, type]) => `export const Lazy${pascalName}: ${type}`).join(',\n')} + export const componentNames: string[] ` + } } diff --git a/packages/schema/src/config/_adhoc.ts b/packages/schema/src/config/_adhoc.ts index 15bed36308c..1d8b2e4ebe6 100644 --- a/packages/schema/src/config/_adhoc.ts +++ b/packages/schema/src/config/_adhoc.ts @@ -18,7 +18,7 @@ export default { return { dirs: val } } if (val === undefined || val === true) { - return { dirs: ['~/components'] } + return { dirs: [{ path: '~/components/global', global: true }, '~/components'] } } return val } diff --git a/test/basic.test.ts b/test/basic.test.ts index b4fcb492bf6..93fbd0f3a47 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -44,6 +44,8 @@ describe('pages', () => { expect(html).toContain('Composable | template: auto imported from ~/components/template.ts') // should import components expect(html).toContain('This is a custom component with a named export.') + expect(html).toContain('global component registered automatically') + expect(html).toContain('global component via suffix') await expectNoClientErrors('/') }) diff --git a/test/fixtures/basic/components/WithSuffix.global.vue b/test/fixtures/basic/components/WithSuffix.global.vue new file mode 100644 index 00000000000..63cfa602077 --- /dev/null +++ b/test/fixtures/basic/components/WithSuffix.global.vue @@ -0,0 +1,3 @@ + diff --git a/test/fixtures/basic/components/global/TestGlobal.vue b/test/fixtures/basic/components/global/TestGlobal.vue new file mode 100644 index 00000000000..41f16ae4995 --- /dev/null +++ b/test/fixtures/basic/components/global/TestGlobal.vue @@ -0,0 +1,3 @@ + diff --git a/test/fixtures/basic/pages/index.vue b/test/fixtures/basic/pages/index.vue index 06903d38513..a96659fb3e7 100644 --- a/test/fixtures/basic/pages/index.vue +++ b/test/fixtures/basic/pages/index.vue @@ -14,6 +14,8 @@ + + From 7091a8685f06cb1b73791f4a7c1bf977834d68d0 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Fri, 22 Jul 2022 15:42:27 +0100 Subject: [PATCH 2/6] fix: regexp --- packages/nuxt/src/components/scan.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nuxt/src/components/scan.ts b/packages/nuxt/src/components/scan.ts index 17a72b35d8f..503ef708e8e 100644 --- a/packages/nuxt/src/components/scan.ts +++ b/packages/nuxt/src/components/scan.ts @@ -63,7 +63,7 @@ export async function scanComponents (dirs: ComponentsDir[], srcDir: string): Pr const global = /\.(global)$/.test(fileName) || dir.global const mode = fileName.match(/(?<=\.)(client|server)(\.global)?$/)?.[1] as 'client' | 'server' || 'all' - fileName = fileName.replace(/(\.client|server)?(\.global)?$/, '') + fileName = fileName.replace(/(\.(client|server))?(\.global)?$/, '') if (fileName.toLowerCase() === 'index') { fileName = dir.pathPrefix === false ? basename(dirname(filePath)) : '' /* inherits from path */ From 9a0c2b07ddafb653f674ee77cd7008b564caff74 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 25 Jul 2022 14:45:45 +0200 Subject: [PATCH 3/6] make path regex more precise --- packages/nuxt/src/components/module.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nuxt/src/components/module.ts b/packages/nuxt/src/components/module.ts index 3f394d13dd4..6dc25def465 100644 --- a/packages/nuxt/src/components/module.ts +++ b/packages/nuxt/src/components/module.ts @@ -13,7 +13,7 @@ function compareDirByPathLength ({ path: pathA }, { path: pathB }) { return pathB.split(/[\\/]/).filter(Boolean).length - pathA.split(/[\\/]/).filter(Boolean).length } -const DEFAULT_COMPONENTS_DIRS_RE = /^(components|global)$/ +const DEFAULT_COMPONENTS_DIRS_RE = /\/components$|\/components\/global$/ export default defineNuxtModule({ meta: { @@ -70,7 +70,7 @@ export default defineNuxtModule({ dirOptions.level = Number(dirOptions.level || 0) const present = isDirectory(dirPath) - if (!present && !DEFAULT_COMPONENTS_DIRS_RE.test(basename(dirOptions.path))) { + if (!present && !DEFAULT_COMPONENTS_DIRS_RE.test(dirOptions.path)) { // eslint-disable-next-line no-console console.warn('Components directory not found: `' + dirPath + '`') } From 610902308af4c82bee4a3bbc725156ee8f7fd3b8 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 25 Jul 2022 15:03:45 +0200 Subject: [PATCH 4/6] fix lint --- packages/nuxt/src/components/module.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nuxt/src/components/module.ts b/packages/nuxt/src/components/module.ts index 6dc25def465..ca8991b19cf 100644 --- a/packages/nuxt/src/components/module.ts +++ b/packages/nuxt/src/components/module.ts @@ -1,5 +1,5 @@ import { statSync } from 'node:fs' -import { resolve, basename } from 'pathe' +import { resolve } from 'pathe' import { defineNuxtModule, resolveAlias, addTemplate, addPluginTemplate } from '@nuxt/kit' import type { Component, ComponentsDir, ComponentsOptions } from '@nuxt/schema' import { componentsPluginTemplate, componentsTemplate, componentsTypeTemplate } from './templates' From 007b125094603e4ea24524755a23f91735073d3d Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 27 Jul 2022 13:36:07 +0200 Subject: [PATCH 5/6] refactor: pass getComponents instead of context to templates --- packages/nuxt/src/components/module.ts | 42 ++++++++++++++--------- packages/nuxt/src/components/templates.ts | 15 ++++---- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/packages/nuxt/src/components/module.ts b/packages/nuxt/src/components/module.ts index ca8991b19cf..845d894fdc5 100644 --- a/packages/nuxt/src/components/module.ts +++ b/packages/nuxt/src/components/module.ts @@ -15,6 +15,8 @@ function compareDirByPathLength ({ path: pathA }, { path: pathB }) { const DEFAULT_COMPONENTS_DIRS_RE = /\/components$|\/components\/global$/ +type getComponentsT = (mode?: 'client' | 'server' | 'all') => Component[] + export default defineNuxtModule({ meta: { name: 'components', @@ -25,7 +27,13 @@ export default defineNuxtModule({ }, setup (componentOptions, nuxt) { let componentDirs = [] - const components: Component[] = [] + const context = { + components: [] as Component[] + } + + const getComponents: getComponentsT = (mode) => { + return context.components.filter(c => c.mode === mode || c.mode === 'all') + } const normalizeDirs = (dir: any, cwd: string) => { if (Array.isArray(dir)) { @@ -95,17 +103,14 @@ export default defineNuxtModule({ nuxt.options.build!.transpile!.push(...componentDirs.filter(dir => dir.transpile).map(dir => dir.path)) }) - const context = { components } - - addTemplate({ - ...componentsTypeTemplate, - options: { context } - }) - - addPluginTemplate({ - ...componentsPluginTemplate, - options: { context } - }) + // components.d.ts + addTemplate({ ...componentsTypeTemplate, options: { getComponents } }) + // components.plugin.mjs + addPluginTemplate({ ...componentsPluginTemplate, options: { getComponents } }) + // components.server.mjs + addTemplate({ ...componentsTemplate, filename: 'components.server.mjs', options: { getComponents, mode: 'server' } }) + // components.client.mjs + addTemplate({ ...componentsTemplate, filename: 'components.client.mjs', options: { getComponents, mode: 'client' } }) nuxt.hook('vite:extendConfig', (config, { isClient }) => { const mode = isClient ? 'client' : 'server' @@ -117,8 +122,6 @@ export default defineNuxtModule({ config.resolve.alias['#components'] = resolve(nuxt.options.buildDir, `components.${mode}.mjs`) } }) - addTemplate({ ...componentsTemplate, filename: 'components.server.mjs', options: { context, mode: 'server' } }) - addTemplate({ ...componentsTemplate, filename: 'components.client.mjs', options: { context, mode: 'client' } }) // Scan components and add to plugin nuxt.hook('app:templates', async () => { @@ -141,7 +144,6 @@ export default defineNuxtModule({ } }) - const getComponents = () => context.components nuxt.hook('vite:extendConfig', (config, { isClient }) => { config.plugins = config.plugins || [] config.plugins.push(loaderPlugin.vite({ @@ -150,7 +152,10 @@ export default defineNuxtModule({ mode: isClient ? 'client' : 'server' })) if (nuxt.options.experimental.treeshakeClientOnly) { - config.plugins.push(TreeShakeTemplatePlugin.vite({ sourcemap: nuxt.options.sourcemap, getComponents })) + config.plugins.push(TreeShakeTemplatePlugin.vite({ + sourcemap: nuxt.options.sourcemap, + getComponents + })) } }) nuxt.hook('webpack:config', (configs) => { @@ -162,7 +167,10 @@ export default defineNuxtModule({ mode: config.name === 'client' ? 'client' : 'server' })) if (nuxt.options.experimental.treeshakeClientOnly) { - config.plugins.push(TreeShakeTemplatePlugin.webpack({ sourcemap: nuxt.options.sourcemap, getComponents })) + config.plugins.push(TreeShakeTemplatePlugin.webpack({ + sourcemap: nuxt.options.sourcemap, + getComponents + })) } }) }) diff --git a/packages/nuxt/src/components/templates.ts b/packages/nuxt/src/components/templates.ts index 1ad552a984b..682cb22c552 100644 --- a/packages/nuxt/src/components/templates.ts +++ b/packages/nuxt/src/components/templates.ts @@ -5,7 +5,7 @@ import { genDynamicImport, genExport, genObjectFromRawEntries } from 'knitwork' export interface ComponentsTemplateContext { nuxt: Nuxt options: { - context: { components: Component[] } + getComponents: (mode?: 'client' | 'server' | 'all') => Component[] mode?: 'client' | 'server' } } @@ -28,7 +28,7 @@ const createImportMagicComments = (options: ImportMagicCommentsOptions) => { export const componentsPluginTemplate = { filename: 'components.plugin.mjs', getContents ({ options }: ComponentsTemplateContext) { - const globalComponents = options.context.components.filter(c => c.global === true) + const globalComponents = options.getComponents().filter(c => c.global === true) return `import { defineAsyncComponent } from 'vue' import { defineNuxtPlugin } from '#app' @@ -51,23 +51,20 @@ export default defineNuxtPlugin(nuxtApp => { } export const componentsTemplate = { + // components.[server|client].mjs' getContents ({ options }: ComponentsTemplateContext) { - const components = options.context.components return [ 'import { defineAsyncComponent } from \'vue\'', - ...components.flatMap((c) => { + ...options.getComponents(options.mode).flatMap((c) => { const exp = c.export === 'default' ? 'c.default || c' : `c['${c.export}']` const comment = createImportMagicComments(c) - // Exclude client/server-only components from other build - if (c.mode !== 'all' && c.mode !== options.mode) { return [] } - return [ genExport(c.filePath, [{ name: c.export, as: c.pascalName }]), `export const Lazy${c.pascalName} = defineAsyncComponent(${genDynamicImport(c.filePath, { comment })}.then(c => ${exp}))` ] }), - `export const componentNames = ${JSON.stringify(components.map(c => c.pascalName))}` + `export const componentNames = ${JSON.stringify(options.getComponents().map(c => c.pascalName))}` ].join('\n') } } @@ -76,7 +73,7 @@ export const componentsTypeTemplate = { filename: 'components.d.ts', getContents: ({ options, nuxt }: ComponentsTemplateContext) => { const buildDir = nuxt.options.buildDir - const componentTypes = options.context.components.map(c => [ + const componentTypes = options.getComponents().map(c => [ c.pascalName, `typeof ${genDynamicImport(isAbsolute(c.filePath) ? relative(buildDir, c.filePath) : c.filePath, { wrapper: false })}['${c.export}']` ]) From df7c5ddcb8d68c5d0a93fdae85433be1f2aba739 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 27 Jul 2022 14:57:37 +0200 Subject: [PATCH 6/6] skip filter when no mode availabl and atomic context update --- packages/nuxt/src/components/module.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/nuxt/src/components/module.ts b/packages/nuxt/src/components/module.ts index 845d894fdc5..45b4921d3fc 100644 --- a/packages/nuxt/src/components/module.ts +++ b/packages/nuxt/src/components/module.ts @@ -32,7 +32,9 @@ export default defineNuxtModule({ } const getComponents: getComponentsT = (mode) => { - return context.components.filter(c => c.mode === mode || c.mode === 'all') + return (mode && mode !== 'all') + ? context.components.filter(c => c.mode === mode || c.mode === 'all') + : context.components } const normalizeDirs = (dir: any, cwd: string) => { @@ -125,8 +127,9 @@ export default defineNuxtModule({ // Scan components and add to plugin nuxt.hook('app:templates', async () => { - context.components = await scanComponents(componentDirs, nuxt.options.srcDir!) - await nuxt.callHook('components:extend', context.components) + const newComponents = await scanComponents(componentDirs, nuxt.options.srcDir!) + await nuxt.callHook('components:extend', newComponents) + context.components = newComponents }) nuxt.hook('prepare:types', ({ references }) => {