From 35fb4064527795a4acbdd6c80f5370f4ac0d3eea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathana=C3=ABl=20Labreuil?= Date: Fri, 15 Mar 2024 23:02:17 +0100 Subject: [PATCH] fix(nuxt): avoid warning about unused page/layout components when mounted asynchronously --- .../src/app/plugins/check-if-layout-used.ts | 4 ++- packages/nuxt/src/components/loader.ts | 14 +++++++++- packages/nuxt/src/components/module.ts | 28 +++++++++++++++++-- .../runtime/plugins/check-if-page-unused.ts | 5 +++- 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/packages/nuxt/src/app/plugins/check-if-layout-used.ts b/packages/nuxt/src/app/plugins/check-if-layout-used.ts index 9cf7192ea98c..247429681c05 100644 --- a/packages/nuxt/src/app/plugins/check-if-layout-used.ts +++ b/packages/nuxt/src/app/plugins/check-if-layout-used.ts @@ -5,6 +5,8 @@ import { useError } from '../composables/error' // @ts-expect-error virtual file import layouts from '#build/layouts' +// @ts-expect-error virtual file +import { isNuxtLayoutUsed } from '#build/detected-nuxt-layout-usage' export default defineNuxtPlugin({ name: 'nuxt:checkIfLayoutUsed', @@ -12,7 +14,7 @@ export default defineNuxtPlugin({ const error = useError() function checkIfLayoutUsed () { - if (!error.value && !nuxtApp._isNuxtLayoutUsed && Object.keys(layouts).length > 0) { + if (!error.value && !nuxtApp._isNuxtLayoutUsed && !isNuxtLayoutUsed && Object.keys(layouts).length > 0) { console.warn('[nuxt] Your project has layouts but the `` component has not been used.') } } diff --git a/packages/nuxt/src/components/loader.ts b/packages/nuxt/src/components/loader.ts index 1f372adfb35e..17daf155c4c0 100644 --- a/packages/nuxt/src/components/loader.ts +++ b/packages/nuxt/src/components/loader.ts @@ -5,7 +5,7 @@ import { pascalCase } from 'scule' import { resolve } from 'pathe' import type { Component, ComponentsOptions } from 'nuxt/schema' -import { logger, tryUseNuxt } from '@nuxt/kit' +import { logger, tryUseNuxt, updateTemplates } from '@nuxt/kit' import { distDir } from '../dirs' import { isVue } from '../core/utils' @@ -15,6 +15,7 @@ interface LoaderOptions { sourcemap?: boolean transform?: ComponentsOptions['transform'] experimentalComponentIslands?: boolean + detectedComponentsUsage: Record } export const loaderPlugin = createUnplugin((options: LoaderOptions) => { @@ -54,6 +55,8 @@ export const loaderPlugin = createUnplugin((options: LoaderOptions) => { let identifier = map.get(component) || `__nuxt_component_${num++}` map.set(component, identifier) + detectComponentUsage(component, options.detectedComponentsUsage) + const isServerOnly = !component._raw && component.mode === 'server' && !components.some(c => c.pascalName === component.pascalName && c.mode === 'client') if (isServerOnly) { @@ -123,3 +126,12 @@ function findComponent (components: Component[], name: string, mode: LoaderOptio // and createServerComponent above return otherModeComponent } + +function detectComponentUsage (component: Component, detectedComponentsUsage: LoaderOptions['detectedComponentsUsage']) { + if (process.env.NODE_ENV !== 'development' || !(component.pascalName in detectedComponentsUsage)) { return } + + detectedComponentsUsage[component.pascalName] = true + const virtualFilename = `detected-${component.kebabName}-usage.mjs` + + updateTemplates({ filter: template => template.filename === virtualFilename }) +} diff --git a/packages/nuxt/src/components/module.ts b/packages/nuxt/src/components/module.ts index 52248d0ad16b..821ed3cf2df2 100644 --- a/packages/nuxt/src/components/module.ts +++ b/packages/nuxt/src/components/module.ts @@ -211,6 +211,28 @@ export default defineNuxtModule({ } }) + const detectedComponentsUsage = { + NuxtLayout: false, + NuxtPage: false + } + + if (process.env.NODE_ENV === 'development') { + addTemplate({ + filename: 'detected-nuxt-layout-usage.mjs', + options: detectedComponentsUsage, + getContents: data => ` + export const isNuxtLayoutUsed = ${data.options.NuxtLayout} + ` + }) + addTemplate({ + filename: 'detected-nuxt-page-usage.mjs', + options: detectedComponentsUsage, + getContents: data => ` + export const isNuxtPageUsed = ${data.options.NuxtPage} + ` + }) + } + nuxt.hook('vite:extendConfig', (config, { isClient, isServer }) => { const mode = isClient ? 'client' : 'server' @@ -230,7 +252,8 @@ export default defineNuxtModule({ getComponents, mode, transform: typeof nuxt.options.components === 'object' && !Array.isArray(nuxt.options.components) ? nuxt.options.components.transform : undefined, - experimentalComponentIslands: !!nuxt.options.experimental.componentIslands + experimentalComponentIslands: !!nuxt.options.experimental.componentIslands, + detectedComponentsUsage })) if (nuxt.options.experimental.componentIslands) { @@ -299,7 +322,8 @@ export default defineNuxtModule({ getComponents, mode, transform: typeof nuxt.options.components === 'object' && !Array.isArray(nuxt.options.components) ? nuxt.options.components.transform : undefined, - experimentalComponentIslands: !!nuxt.options.experimental.componentIslands + experimentalComponentIslands: !!nuxt.options.experimental.componentIslands, + detectedComponentsUsage })) if (nuxt.options.experimental.componentIslands) { diff --git a/packages/nuxt/src/pages/runtime/plugins/check-if-page-unused.ts b/packages/nuxt/src/pages/runtime/plugins/check-if-page-unused.ts index 57ae91fe6e63..ff747425082f 100644 --- a/packages/nuxt/src/pages/runtime/plugins/check-if-page-unused.ts +++ b/packages/nuxt/src/pages/runtime/plugins/check-if-page-unused.ts @@ -3,13 +3,16 @@ import { defineNuxtPlugin } from '#app/nuxt' import { onNuxtReady } from '#app/composables/ready' import { useError } from '#app/composables/error' +// @ts-expect-error virtual file +import { isNuxtPageUsed } from '#build/detected-nuxt-page-usage' + export default defineNuxtPlugin({ name: 'nuxt:checkIfPageUnused', setup (nuxtApp) { const error = useError() function checkIfPageUnused () { - if (!error.value && !nuxtApp._isNuxtPageUsed) { + if (!error.value && !nuxtApp._isNuxtPageUsed && !isNuxtPageUsed) { console.warn( '[nuxt] Your project has pages but the `` component has not been used.' + ' You might be using the `` component instead, which will not work correctly in Nuxt.' +