diff --git a/packages/nuxt3/package.json b/packages/nuxt3/package.json index 5ba4e7880b..c44a05f897 100644 --- a/packages/nuxt3/package.json +++ b/packages/nuxt3/package.json @@ -49,6 +49,7 @@ "hash-sum": "^2.0.0", "hookable": "^5.1.1", "knitwork": "^0.1.0", + "magic-string-extra": "^0.1.2", "mlly": "^0.4.3", "murmurhash-es": "^0.1.1", "nitropack": "npm:nitropack-edge@latest", diff --git a/packages/nuxt3/src/components/loader.ts b/packages/nuxt3/src/components/loader.ts index 02f6d84e18..4a7e1af859 100644 --- a/packages/nuxt3/src/components/loader.ts +++ b/packages/nuxt3/src/components/loader.ts @@ -2,6 +2,7 @@ import { createUnplugin } from 'unplugin' import { parseQuery, parseURL } from 'ufo' import { Component } from '@nuxt/schema' import { genImport } from 'knitwork' +import MagicString from 'magic-string-extra' interface LoaderOptions { getComponents(): Component[] @@ -17,8 +18,8 @@ export const loaderPlugin = createUnplugin((options: LoaderOptions) => ({ // from `type=template` (in Webpack) and bare `.vue` file (in Vite) return pathname.endsWith('.vue') && (query.type === 'template' || !search) }, - transform (code) { - return transform(code, options.getComponents()) + transform (code, id) { + return transform(code, id, options.getComponents()) } })) @@ -26,13 +27,14 @@ function findComponent (components: Component[], name:string) { return components.find(({ pascalName, kebabName }) => [pascalName, kebabName].includes(name)) } -function transform (content: string, components: Component[]) { +function transform (code: string, id: string, components: Component[]) { let num = 0 let imports = '' const map = new Map() + const s = new MagicString(code) // replace `_resolveComponent("...")` to direct import - const newContent = content.replace(/ _resolveComponent\("(.*?)"\)/g, (full, name) => { + s.replace(/ _resolveComponent\("(.*?)"\)/g, (full, name) => { const component = findComponent(components, name) if (component) { const identifier = map.get(component) || `__nuxt_component_${num++}` @@ -44,7 +46,9 @@ function transform (content: string, components: Component[]) { return full }) - if (!imports || newContent === content) { return } + if (imports) { + s.prepend(imports + '\n') + } - return `${imports}\n${newContent}` + return s.toRollupResult(true, { source: id, includeContent: true }) } diff --git a/yarn.lock b/yarn.lock index 6353c81a52..e67c663c0f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13761,6 +13761,15 @@ __metadata: languageName: node linkType: hard +"magic-string-extra@npm:^0.1.2": + version: 0.1.2 + resolution: "magic-string-extra@npm:0.1.2" + dependencies: + magic-string: ^0.25.7 + checksum: 196dec128985162ff559752dd28f358bacd203e9e9e2bcb7d3eb8a1cdacc8a60ce1d49709f31de16f594adb60566959dbb04750560c3cbc872f520d062dba0ee + languageName: node + linkType: hard + "magic-string@npm:^0.25.7": version: 0.25.7 resolution: "magic-string@npm:0.25.7" @@ -15418,6 +15427,7 @@ __metadata: hash-sum: ^2.0.0 hookable: ^5.1.1 knitwork: ^0.1.0 + magic-string-extra: ^0.1.2 mlly: ^0.4.3 murmurhash-es: ^0.1.1 nitropack: "npm:nitropack-edge@latest"