Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(nuxt): pass joinRelativeURL to bundle renderer and share paths with nitro #26407

Merged
merged 11 commits into from
Mar 21, 2024
2 changes: 1 addition & 1 deletion packages/nuxt/src/app/composables/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useRuntimeConfig } from '../nuxt'
// @ts-expect-error virtual file
import { appManifest as isAppManifestEnabled } from '#build/nuxt.config.mjs'
// @ts-expect-error virtual file
import { buildAssetsURL } from '#build/paths.mjs'
import { buildAssetsURL } from '#paths'

export interface NuxtAppManifestMeta {
id: string
Expand Down
2 changes: 1 addition & 1 deletion packages/nuxt/src/app/entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { App } from 'vue'

// These files must be imported first as they have side effects:
// 1. (we set __webpack_public_path via this import, if using webpack builder)
import '#build/paths.mjs'
import '#paths'
// 2. we set globalThis.$fetch via this import
import '#build/fetch.mjs'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getAppManifest } from '../composables/manifest'
import type { NuxtAppManifestMeta } from '../composables/manifest'
import { onNuxtReady } from '../composables/ready'
// @ts-expect-error virtual file
import { buildAssetsURL } from '#build/paths.mjs'
import { buildAssetsURL } from '#paths'

export default defineNuxtPlugin((nuxtApp) => {
if (import.meta.test) { return }
Expand Down
6 changes: 3 additions & 3 deletions packages/nuxt/src/core/runtime/nitro/paths.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { joinURL } from 'ufo'
import { joinRelativeURL } from 'ufo'
import { useRuntimeConfig } from '#internal/nitro'

export function baseURL (): string {
Expand All @@ -12,12 +12,12 @@ export function buildAssetsDir (): string {
}

export function buildAssetsURL (...path: string[]): string {
return joinURL(publicAssetsURL(), buildAssetsDir(), ...path)
return joinRelativeURL(publicAssetsURL(), buildAssetsDir(), ...path)
}

export function publicAssetsURL (...path: string[]): string {
// TODO: support passing event to `useRuntimeConfig`
const app = useRuntimeConfig().app
const publicBase = app.cdnURL as string || app.baseURL
return path.length ? joinURL(publicBase, ...path) : publicBase
return path.length ? joinRelativeURL(publicBase, ...path) : publicBase
}
8 changes: 4 additions & 4 deletions packages/nuxt/src/core/templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ export const publicPathTemplate: NuxtTemplate = {
filename: 'paths.mjs',
getContents ({ nuxt }) {
return [
'import { joinRelativeURL as joinURL } from \'ufo\'',
'import { joinRelativeURL } from \'ufo\'',
!nuxt.options.dev && 'import { useRuntimeConfig } from \'#internal/nitro\'',

nuxt.options.dev
Expand All @@ -337,11 +337,11 @@ export const publicPathTemplate: NuxtTemplate = {
'export const baseURL = () => appConfig.baseURL',
'export const buildAssetsDir = () => appConfig.buildAssetsDir',

'export const buildAssetsURL = (...path) => joinURL(publicAssetsURL(), buildAssetsDir(), ...path)',
'export const buildAssetsURL = (...path) => joinRelativeURL(publicAssetsURL(), buildAssetsDir(), ...path)',

'export const publicAssetsURL = (...path) => {',
' const publicBase = appConfig.cdnURL || appConfig.baseURL',
' return path.length ? joinURL(publicBase, ...path) : publicBase',
' return path.length ? joinRelativeURL(publicBase, ...path) : publicBase',
'}',

// On server these are registered directly in packages/nuxt/src/core/runtime/nitro/renderer.ts
Expand All @@ -358,7 +358,7 @@ export const dollarFetchTemplate: NuxtTemplate = {
getContents () {
return [
'import { $fetch } from \'ofetch\'',
"import { baseURL } from '#build/paths.mjs'",
"import { baseURL } from '#paths'",
'if (!globalThis.$fetch) {',
' globalThis.$fetch = $fetch.create({',
' baseURL: baseURL()',
Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export async function buildClient (ctx: ViteBuildContext) {
alias: {
...nodeCompat.alias,
...ctx.config.resolve?.alias,
'#paths': resolve(ctx.nuxt.options.buildDir, 'paths.mjs'),
'#build/plugins': resolve(ctx.nuxt.options.buildDir, 'plugins/client'),
'#internal/nitro': resolve(ctx.nuxt.options.buildDir, 'nitro.client.mjs')
},
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/plugins/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function runtimePathsPlugin (options: RuntimePathsOptions): Plugin {
if (VITE_ASSET_RE.test(code)) {
const s = new MagicString(code)
// Register dependency on paths.mjs, which sets globalThis.__publicAssetsURL
s.prepend('import "#build/paths.mjs";')
s.prepend('import "#paths";')

return {
code: s.toString(),
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/plugins/public-dirs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const VitePublicDirsPlugin = createUnplugin(() => {
enforce: 'pre',
handler (id) {
if (id.startsWith(PREFIX)) {
return `import { publicAssetsURL } from '#build/paths.mjs';export default publicAssetsURL(${JSON.stringify(decodeURIComponent(id.slice(PREFIX.length)))})`
return `import { publicAssetsURL } from '#paths';export default publicAssetsURL(${JSON.stringify(decodeURIComponent(id.slice(PREFIX.length)))})`
}
}
},
Expand Down
17 changes: 10 additions & 7 deletions packages/vite/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export async function buildServer (ctx: ViteBuildContext) {
},
resolve: {
alias: {
'#paths': resolve(ctx.nuxt.options.buildDir, 'paths.mjs'),
'#build/plugins': resolve(ctx.nuxt.options.buildDir, 'plugins/server')
}
},
Expand All @@ -79,7 +80,7 @@ export async function buildServer (ctx: ViteBuildContext) {
ssr: true,
rollupOptions: {
input: { server: entry },
external: ['#internal/nitro'],
external: ['#internal/nitro', '#paths'],
output: {
entryFileNames: '[name].mjs',
format: 'module',
Expand All @@ -105,12 +106,14 @@ export async function buildServer (ctx: ViteBuildContext) {
if (!ctx.nuxt.options.dev) {
const nitroDependencies = await tryResolveModule('nitropack/package.json', ctx.nuxt.options.modulesDir)
.then(r => import(r!)).then(r => Object.keys(r.dependencies || {})).catch(() => [])
;(serverConfig.ssr!.external as string[])!.push(
// explicit dependencies we use in our ssr renderer - these can be inlined (if necessary) in the nitro build
'unhead', '@unhead/ssr', 'unctx', 'h3', 'devalue', '@nuxt/devalue', 'radix3', 'unstorage', 'hookable',
// dependencies we might share with nitro - these can be inlined (if necessary) in the nitro build
...nitroDependencies
)
if (Array.isArray(serverConfig.ssr!.external)) {
serverConfig.ssr!.external.push(
// explicit dependencies we use in our ssr renderer - these can be inlined (if necessary) in the nitro build
'unhead', '@unhead/ssr', 'unctx', 'h3', 'devalue', '@nuxt/devalue', 'radix3', 'unstorage', 'hookable',
// dependencies we might share with nitro - these can be inlined (if necessary) in the nitro build
...nitroDependencies
)
}
}

serverConfig.customLogger = createViteLogger(serverConfig)
Expand Down
3 changes: 3 additions & 0 deletions packages/webpack/src/configs/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ function serverStandalone (ctx: WebpackConfigContext) {
...ctx.options.build.transpile
]
const external = ['#internal/nitro']
if (!ctx.nuxt.options.dev) {
external.push('#paths')
}

if (!Array.isArray(ctx.config.externals)) { return }
ctx.config.externals.push(({ request }, cb) => {
Expand Down
1 change: 1 addition & 0 deletions packages/webpack/src/presets/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ function baseAlias (ctx: WebpackConfigContext) {
'#app': ctx.options.appDir,
'#build/plugins': resolve(ctx.options.buildDir, 'plugins', ctx.isClient ? 'client' : 'server'),
'#build': ctx.options.buildDir,
'#paths': resolve(ctx.nuxt.options.buildDir, 'paths.mjs'),
...ctx.options.alias,
...ctx.alias
}
Expand Down
4 changes: 2 additions & 2 deletions test/bundle.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM
const serverDir = join(rootDir, '.output/server')

const serverStats = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot('"206k"')
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot('"207k"')

const modules = await analyzeSizes('node_modules/**/*', serverDir)
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot('"1336k"')
Expand Down Expand Up @@ -72,7 +72,7 @@ describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM
const serverDir = join(rootDir, '.output-inline/server')

const serverStats = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot('"525k"')
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot('"526k"')

const modules = await analyzeSizes('node_modules/**/*', serverDir)
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot('"77.8k"')
Expand Down
2 changes: 1 addition & 1 deletion vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default defineConfig({
resolve: {
alias: {
'#build/nuxt.config.mjs': resolve('./test/mocks/nuxt-config'),
'#build/paths.mjs': resolve('./test/mocks/paths'),
'#paths': resolve('./test/mocks/paths'),
pi0 marked this conversation as resolved.
Show resolved Hide resolved
'#build/app.config.mjs': resolve('./test/mocks/app-config'),
'#app': resolve('./packages/nuxt/dist/app')
}
Expand Down