From 2e705fb28963e49997c3839f5208d33cad32eedc Mon Sep 17 00:00:00 2001 From: Julien Huang Date: Thu, 4 Apr 2024 20:03:15 +0200 Subject: [PATCH] perf: don't add global component plugin if not used --- .../nuxt/src/components/global-components.ts | 52 +++++++++++++++++++ packages/nuxt/src/components/module.ts | 10 +++- packages/nuxt/src/components/templates.ts | 46 +--------------- playground/nuxt.config.ts | 4 +- 4 files changed, 64 insertions(+), 48 deletions(-) create mode 100644 packages/nuxt/src/components/global-components.ts diff --git a/packages/nuxt/src/components/global-components.ts b/packages/nuxt/src/components/global-components.ts new file mode 100644 index 0000000000..4c2645bb8c --- /dev/null +++ b/packages/nuxt/src/components/global-components.ts @@ -0,0 +1,52 @@ +import { NuxtApp, NuxtPluginTemplate } from "@nuxt/schema" + +interface GetGlobalComponentsType { + lazyGlobalComponents: Set + syncGlobalComponents: Set +} + +export function getGlobalComponents(app: NuxtApp): GetGlobalComponentsType | null { + const lazyGlobalComponents = new Set() + const syncGlobalComponents = new Set() + for (const component of app.components) { + if (component.global === 'sync') { + syncGlobalComponents.add(component.pascalName) + } else if (component.global) { + lazyGlobalComponents.add(component.pascalName) + } + } + // will not be imported and be treeshaken + if (!lazyGlobalComponents.size && !syncGlobalComponents.size) { return null } + + return { + lazyGlobalComponents, + syncGlobalComponents + } +} + +export const getComponentsPluginTemplate: (components: GetGlobalComponentsType) => NuxtPluginTemplate = ({lazyGlobalComponents, syncGlobalComponents}) => ({ + filename: 'components.plugin.mjs', + write: true, + getContents () { + const lazyComponents = [...lazyGlobalComponents] + const syncComponents = [...syncGlobalComponents] + + return `import { defineNuxtPlugin } from '#app/nuxt' +import { ${[...lazyComponents.map(c => 'Lazy' + c), ...syncComponents].join(', ')} } from '#components' +const lazyGlobalComponents = [ + ${lazyComponents.map(c => `["${c}", Lazy${c}]`).join(',\n')}, + ${syncComponents.map(c => `["${c}", ${c}]`).join(',\n')} +] + +export default defineNuxtPlugin({ + name: 'nuxt:global-components', + setup (nuxtApp) { + for (const [name, component] of lazyGlobalComponents) { + nuxtApp.vueApp.component(name, component) + nuxtApp.vueApp.component('Lazy' + name, component) + } + } +}) +` + } +}) \ No newline at end of file diff --git a/packages/nuxt/src/components/module.ts b/packages/nuxt/src/components/module.ts index bcc6fb259b..f74128b1e0 100644 --- a/packages/nuxt/src/components/module.ts +++ b/packages/nuxt/src/components/module.ts @@ -5,12 +5,13 @@ import type { Component, ComponentsDir, ComponentsOptions } from 'nuxt/schema' import { distDir } from '../dirs' import { clientFallbackAutoIdPlugin } from './client-fallback-auto-id' -import { componentNamesTemplate, componentsIslandsTemplate, componentsPluginTemplate, componentsTypeTemplate } from './templates' +import { componentNamesTemplate, componentsIslandsTemplate, componentsTypeTemplate } from './templates' import { scanComponents } from './scan' import { loaderPlugin } from './loader' import { TreeShakeTemplatePlugin } from './tree-shake' import { componentsChunkPlugin, islandsTransform } from './islandsTransform' import { createTransformPlugin } from './transform' +import { getComponentsPluginTemplate, getGlobalComponents } from './global-components' const isPureObjectOrString = (val: any) => (!Array.isArray(val) && typeof val === 'object') || typeof val === 'string' const isDirectory = (p: string) => { try { return statSync(p).isDirectory() } catch (_e) { return false } } @@ -117,7 +118,6 @@ export default defineNuxtModule({ // components.d.ts addTemplate(componentsTypeTemplate) // components.plugin.mjs - addPluginTemplate(componentsPluginTemplate) // component-names.mjs addTemplate(componentNamesTemplate) // components.islands.mjs @@ -179,6 +179,12 @@ export default defineNuxtModule({ } context.components = newComponents app.components = newComponents + + const globalComponents = getGlobalComponents(app) + if (globalComponents) { + console.log('!!', getComponentsPluginTemplate(globalComponents)) + addPluginTemplate(getComponentsPluginTemplate(globalComponents)) + } }) nuxt.hook('prepare:types', ({ references, tsConfig }) => { diff --git a/packages/nuxt/src/components/templates.ts b/packages/nuxt/src/components/templates.ts index 5d751a705d..2595d15bd0 100644 --- a/packages/nuxt/src/components/templates.ts +++ b/packages/nuxt/src/components/templates.ts @@ -1,6 +1,6 @@ import { isAbsolute, relative } from 'pathe' import { genDynamicImport } from 'knitwork' -import type { NuxtPluginTemplate, NuxtTemplate } from 'nuxt/schema' +import type { NuxtTemplate } from 'nuxt/schema' type ImportMagicCommentsOptions = { chunkName: string @@ -17,50 +17,6 @@ const createImportMagicComments = (options: ImportMagicCommentsOptions) => { ].filter(Boolean).join(', ') } -const emptyComponentsPlugin = ` -import { defineNuxtPlugin } from '#app/nuxt' -export default defineNuxtPlugin({ - name: 'nuxt:global-components', -}) -` - -export const componentsPluginTemplate: NuxtPluginTemplate = { - filename: 'components.plugin.mjs', - getContents ({ app }) { - const lazyGlobalComponents = new Set() - const syncGlobalComponents = new Set() - for (const component of app.components) { - if (component.global === 'sync') { - syncGlobalComponents.add(component.pascalName) - } else if (component.global) { - lazyGlobalComponents.add(component.pascalName) - } - } - if (!lazyGlobalComponents.size && !syncGlobalComponents.size) { return emptyComponentsPlugin } - - const lazyComponents = [...lazyGlobalComponents] - const syncComponents = [...syncGlobalComponents] - - return `import { defineNuxtPlugin } from '#app/nuxt' -import { ${[...lazyComponents.map(c => 'Lazy' + c), ...syncComponents].join(', ')} } from '#components' -const lazyGlobalComponents = [ - ${lazyComponents.map(c => `["${c}", Lazy${c}]`).join(',\n')}, - ${syncComponents.map(c => `["${c}", ${c}]`).join(',\n')} -] - -export default defineNuxtPlugin({ - name: 'nuxt:global-components', - setup (nuxtApp) { - for (const [name, component] of lazyGlobalComponents) { - nuxtApp.vueApp.component(name, component) - nuxtApp.vueApp.component('Lazy' + name, component) - } - } -}) -` - } -} - export const componentNamesTemplate: NuxtTemplate = { filename: 'component-names.mjs', getContents ({ app }) { diff --git a/playground/nuxt.config.ts b/playground/nuxt.config.ts index 896312f044..27369722d7 100644 --- a/playground/nuxt.config.ts +++ b/playground/nuxt.config.ts @@ -1,3 +1,5 @@ export default defineNuxtConfig({ - +devtools: { + enabled:true +} })