From dda338a1dcfadb0056db04faedd3b3096a16c439 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Thu, 18 May 2023 15:10:12 +0100 Subject: [PATCH] fix(nuxt): resolve layer assets in relation to layer directory (#20932) --- packages/nuxt/src/core/nuxt.ts | 4 ++ .../nuxt/src/core/plugins/layer-aliasing.ts | 37 ++++++++++++++----- .../bar/components/ExtendsOverride.vue | 1 + .../basic/extends/bar/public/nuxt.svg | 18 +++++++++ 4 files changed, 51 insertions(+), 9 deletions(-) create mode 100644 test/fixtures/basic/extends/bar/public/nuxt.svg diff --git a/packages/nuxt/src/core/nuxt.ts b/packages/nuxt/src/core/nuxt.ts index 77c1d320ce..182a7bb337 100644 --- a/packages/nuxt/src/core/nuxt.ts +++ b/packages/nuxt/src/core/nuxt.ts @@ -86,11 +86,15 @@ async function initNuxt (nuxt: Nuxt) { // Add layer aliasing support for ~, ~~, @ and @@ aliases addVitePlugin(() => LayerAliasingPlugin.vite({ sourcemap: nuxt.options.sourcemap.server || nuxt.options.sourcemap.client, + dev: nuxt.options.dev, + root: nuxt.options.srcDir, // skip top-level layer (user's project) as the aliases will already be correctly resolved layers: nuxt.options._layers.slice(1) })) addWebpackPlugin(() => LayerAliasingPlugin.webpack({ sourcemap: nuxt.options.sourcemap.server || nuxt.options.sourcemap.client, + dev: nuxt.options.dev, + root: nuxt.options.srcDir, // skip top-level layer (user's project) as the aliases will already be correctly resolved layers: nuxt.options._layers.slice(1), transform: true diff --git a/packages/nuxt/src/core/plugins/layer-aliasing.ts b/packages/nuxt/src/core/plugins/layer-aliasing.ts index 9c47d65c13..c085452a38 100644 --- a/packages/nuxt/src/core/plugins/layer-aliasing.ts +++ b/packages/nuxt/src/core/plugins/layer-aliasing.ts @@ -1,24 +1,37 @@ +import { existsSync, readdirSync } from 'node:fs' import { createUnplugin } from 'unplugin' import type { NuxtConfigLayer } from 'nuxt/schema' import { resolveAlias } from '@nuxt/kit' -import { normalize } from 'pathe' +import { join, normalize, relative } from 'pathe' import MagicString from 'magic-string' interface LayerAliasingOptions { sourcemap?: boolean transform?: boolean + root: string + dev: boolean layers: NuxtConfigLayer[] } const ALIAS_RE = /(?<=['"])[~@]{1,2}(?=\/)/g export const LayerAliasingPlugin = createUnplugin((options: LayerAliasingOptions) => { - const aliases = Object.fromEntries(options.layers.map(l => [l.config.srcDir || l.cwd, { - '~': l.config?.alias?.['~'] || l.config.srcDir || l.cwd, - '@': l.config?.alias?.['@'] || l.config.srcDir || l.cwd, - '~~': l.config?.alias?.['~~'] || l.config.rootDir || l.cwd, - '@@': l.config?.alias?.['@@'] || l.config.rootDir || l.cwd - }])) + const aliases = Object.fromEntries(options.layers.map((l) => { + const srcDir = l.config.srcDir || l.cwd + const rootDir = l.config.rootDir || l.cwd + const publicDir = join(srcDir, l.config?.dir?.public || 'public') + + return [srcDir, { + aliases: { + '~': l.config?.alias?.['~'] || srcDir, + '@': l.config?.alias?.['@'] || srcDir, + '~~': l.config?.alias?.['~~'] || rootDir, + '@@': l.config?.alias?.['@@'] || rootDir + }, + prefix: relative(options.root, publicDir), + publicDir: !options.dev && existsSync(publicDir) && publicDir + }] + })) const layers = Object.keys(aliases).sort((a, b) => b.length - a.length) return { @@ -33,7 +46,13 @@ export const LayerAliasingPlugin = createUnplugin((options: LayerAliasingOptions const layer = layers.find(l => importer.startsWith(l)) if (!layer) { return } - const resolvedId = resolveAlias(id, aliases[layer]) + const publicDir = aliases[layer].publicDir + if (id.startsWith('/') && publicDir && readdirSync(publicDir).some(file => file === id.slice(1) || id.startsWith('/' + file + '/'))) { + const resolvedId = '/' + join(aliases[layer].prefix, id.slice(1)) + return await this.resolve(resolvedId, importer, { skipSelf: true }) + } + + const resolvedId = resolveAlias(id, aliases[layer].aliases) if (resolvedId !== id) { return await this.resolve(resolvedId, importer, { skipSelf: true }) } @@ -55,7 +74,7 @@ export const LayerAliasingPlugin = createUnplugin((options: LayerAliasingOptions if (!layer || !code.match(ALIAS_RE)) { return } const s = new MagicString(code) - s.replace(ALIAS_RE, r => aliases[layer][r as '~'] || r) + s.replace(ALIAS_RE, r => aliases[layer].aliases[r as '~'] || r) if (s.hasChanged()) { return { diff --git a/test/fixtures/basic/extends/bar/components/ExtendsOverride.vue b/test/fixtures/basic/extends/bar/components/ExtendsOverride.vue index 070c0c5d43..01a809c4f4 100644 --- a/test/fixtures/basic/extends/bar/components/ExtendsOverride.vue +++ b/test/fixtures/basic/extends/bar/components/ExtendsOverride.vue @@ -1,3 +1,4 @@ diff --git a/test/fixtures/basic/extends/bar/public/nuxt.svg b/test/fixtures/basic/extends/bar/public/nuxt.svg new file mode 100644 index 0000000000..c31de56afc --- /dev/null +++ b/test/fixtures/basic/extends/bar/public/nuxt.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + +