diff --git a/packages/nuxt/src/core/utils/index.ts b/packages/nuxt/src/core/utils/index.ts index 48daaef37e..2653f9a993 100644 --- a/packages/nuxt/src/core/utils/index.ts +++ b/packages/nuxt/src/core/utils/index.ts @@ -1,5 +1,5 @@ export { getNameFromPath, hasSuffix, resolveComponentNameSegments } from './names' -export { isJS, isVue } from './plugins' +export { getLoader, isJS, isVue } from './plugins' export function uniqueBy (arr: T[], key: K) { if (arr.length < 2) { diff --git a/packages/nuxt/src/core/utils/plugins.ts b/packages/nuxt/src/core/utils/plugins.ts index b8edfe9bd7..1e80ddb07d 100644 --- a/packages/nuxt/src/core/utils/plugins.ts +++ b/packages/nuxt/src/core/utils/plugins.ts @@ -1,4 +1,5 @@ import { pathToFileURL } from 'node:url' +import { extname } from 'pathe' import { parseQuery, parseURL } from 'ufo' export function isVue (id: string, opts: { type?: Array<'template' | 'script' | 'style'> } = {}) { @@ -41,3 +42,15 @@ export function isJS (id: string) { const { pathname } = parseURL(decodeURIComponent(pathToFileURL(id).href)) return JS_RE.test(pathname) } + +export function getLoader (id: string): 'vue' | 'ts' | 'tsx' | null { + const { pathname } = parseURL(decodeURIComponent(pathToFileURL(id).href)) + const ext = extname(pathname) + if (ext === '.vue') { + return 'vue' + } + if (!JS_RE.test(ext)) { + return null + } + return ext.endsWith('x') ? 'tsx' : 'ts' +} diff --git a/packages/nuxt/src/pages/utils.ts b/packages/nuxt/src/pages/utils.ts index 2c2a09a9d0..75400bcdc8 100644 --- a/packages/nuxt/src/pages/utils.ts +++ b/packages/nuxt/src/pages/utils.ts @@ -13,7 +13,7 @@ import { walk } from 'estree-walker' import type { CallExpression, ExpressionStatement, ObjectExpression, Program, Property } from 'estree' import type { NuxtPage } from 'nuxt/schema' -import { uniqueBy } from '../core/utils' +import { getLoader, uniqueBy } from '../core/utils' import { toArray } from '../utils' import { distDir } from '../dirs' @@ -188,7 +188,8 @@ export async function getRouteMeta (contents: string, absolutePath: string): Pro if (absolutePath in metaCache) { return metaCache[absolutePath] } - const script = extractScriptContent(contents) + const loader = getLoader(absolutePath) + const script = !loader ? null : loader === 'vue' ? extractScriptContent(contents) : { code: contents, loader } if (!script) { metaCache[absolutePath] = {} return {} diff --git a/packages/nuxt/test/page-metadata.test.ts b/packages/nuxt/test/page-metadata.test.ts index 01d98b9503..337871af5f 100644 --- a/packages/nuxt/test/page-metadata.test.ts +++ b/packages/nuxt/test/page-metadata.test.ts @@ -10,6 +10,16 @@ describe('page metadata', () => { expect(await getRouteMeta('', filePath)).toEqual({}) }) + it('should extract metadata from JS/JSX files', async () => { + const fileContents = `definePageMeta({ name: 'bar' })` + for (const ext of ['js', 'jsx', 'ts', 'tsx', 'mjs', 'cjs']) { + const meta = await getRouteMeta(fileContents, `/app/pages/index.${ext}`) + expect(meta).toStrictEqual({ + name: 'bar', + }) + } + }) + it('should use and invalidate cache', async () => { const fileContents = `` const meta = await getRouteMeta(fileContents, filePath)