mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-22 05:35:13 +00:00
fix(nuxt, vite): do not use cjs utils to resolve/alias vue (#21837)
This commit is contained in:
parent
1cc22aa4aa
commit
e023c06353
1
.gitignore
vendored
1
.gitignore
vendored
@ -23,6 +23,7 @@ dist
|
|||||||
.vercel
|
.vercel
|
||||||
.netlify
|
.netlify
|
||||||
.output
|
.output
|
||||||
|
.output-*
|
||||||
.gen
|
.gen
|
||||||
|
|
||||||
# Junit reports
|
# Junit reports
|
||||||
|
@ -2,7 +2,7 @@ import { existsSync, promises as fsp, readFileSync } from 'node:fs'
|
|||||||
import { join, relative, resolve } from 'pathe'
|
import { join, relative, resolve } from 'pathe'
|
||||||
import { build, copyPublicAssets, createDevServer, createNitro, prepare, prerender, scanHandlers, writeTypes } from 'nitropack'
|
import { build, copyPublicAssets, createDevServer, createNitro, prepare, prerender, scanHandlers, writeTypes } from 'nitropack'
|
||||||
import type { Nitro, NitroConfig } from 'nitropack'
|
import type { Nitro, NitroConfig } from 'nitropack'
|
||||||
import { logger, resolvePath } from '@nuxt/kit'
|
import { logger } from '@nuxt/kit'
|
||||||
import escapeRE from 'escape-string-regexp'
|
import escapeRE from 'escape-string-regexp'
|
||||||
import { defu } from 'defu'
|
import { defu } from 'defu'
|
||||||
import fsExtra from 'fs-extra'
|
import fsExtra from 'fs-extra'
|
||||||
@ -165,13 +165,6 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
alias: {
|
alias: {
|
||||||
...nuxt.options.experimental.externalVue
|
|
||||||
? {}
|
|
||||||
: {
|
|
||||||
'vue/compiler-sfc': 'vue/compiler-sfc',
|
|
||||||
'vue/server-renderer': 'vue/server-renderer',
|
|
||||||
vue: await resolvePath(`vue/dist/vue.cjs${nuxt.options.dev ? '' : '.prod'}.js`)
|
|
||||||
},
|
|
||||||
// Vue 3 mocks
|
// Vue 3 mocks
|
||||||
...nuxt.options.vue.runtimeCompiler || nuxt.options.experimental.externalVue
|
...nuxt.options.vue.runtimeCompiler || nuxt.options.experimental.externalVue
|
||||||
? {}
|
? {}
|
||||||
|
@ -58,7 +58,6 @@ export async function buildClient (ctx: ViteBuildContext) {
|
|||||||
// runtime compiler
|
// runtime compiler
|
||||||
'@vue/compiler-sfc', '@vue/compiler-dom', '@vue/compiler-core', '@vue/compiler-ssr'
|
'@vue/compiler-sfc', '@vue/compiler-dom', '@vue/compiler-core', '@vue/compiler-ssr'
|
||||||
]
|
]
|
||||||
|
|
||||||
},
|
},
|
||||||
cacheDir: resolve(ctx.nuxt.options.rootDir, 'node_modules/.cache/vite', 'client'),
|
cacheDir: resolve(ctx.nuxt.options.rootDir, 'node_modules/.cache/vite', 'client'),
|
||||||
build: {
|
build: {
|
||||||
|
@ -2,7 +2,7 @@ import { resolve } from 'pathe'
|
|||||||
import * as vite from 'vite'
|
import * as vite from 'vite'
|
||||||
import vuePlugin from '@vitejs/plugin-vue'
|
import vuePlugin from '@vitejs/plugin-vue'
|
||||||
import viteJsxPlugin from '@vitejs/plugin-vue-jsx'
|
import viteJsxPlugin from '@vitejs/plugin-vue-jsx'
|
||||||
import { logger, resolveModule, resolvePath } from '@nuxt/kit'
|
import { logger, resolvePath } from '@nuxt/kit'
|
||||||
import { joinURL, withTrailingSlash, withoutLeadingSlash } from 'ufo'
|
import { joinURL, withTrailingSlash, withoutLeadingSlash } from 'ufo'
|
||||||
import type { ViteConfig } from '@nuxt/schema'
|
import type { ViteConfig } from '@nuxt/schema'
|
||||||
import type { ViteBuildContext } from './vite'
|
import type { ViteBuildContext } from './vite'
|
||||||
@ -13,7 +13,6 @@ import { writeManifest } from './manifest'
|
|||||||
import { transpile } from './utils/transpile'
|
import { transpile } from './utils/transpile'
|
||||||
|
|
||||||
export async function buildServer (ctx: ViteBuildContext) {
|
export async function buildServer (ctx: ViteBuildContext) {
|
||||||
const _resolve = (id: string) => resolveModule(id, { paths: ctx.nuxt.options.modulesDir })
|
|
||||||
const helper = ctx.nuxt.options.nitro.imports !== false ? '' : 'globalThis.'
|
const helper = ctx.nuxt.options.nitro.imports !== false ? '' : 'globalThis.'
|
||||||
const entry = ctx.nuxt.options.ssr ? ctx.entry : await resolvePath(resolve(ctx.nuxt.options.appDir, 'entry-spa'))
|
const entry = ctx.nuxt.options.ssr ? ctx.entry : await resolvePath(resolve(ctx.nuxt.options.appDir, 'entry-spa'))
|
||||||
const serverConfig: ViteConfig = vite.mergeConfig(ctx.config, {
|
const serverConfig: ViteConfig = vite.mergeConfig(ctx.config, {
|
||||||
@ -53,23 +52,11 @@ export async function buildServer (ctx: ViteBuildContext) {
|
|||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'#build/plugins': resolve(ctx.nuxt.options.buildDir, 'plugins/server'),
|
'#build/plugins': resolve(ctx.nuxt.options.buildDir, 'plugins/server')
|
||||||
...ctx.nuxt.options.experimental.externalVue || ctx.nuxt.options.dev
|
|
||||||
? {}
|
|
||||||
: {
|
|
||||||
'@vue/reactivity': _resolve(`@vue/reactivity/dist/reactivity.cjs${ctx.nuxt.options.dev ? '' : '.prod'}.js`),
|
|
||||||
'@vue/shared': _resolve(`@vue/shared/dist/shared.cjs${ctx.nuxt.options.dev ? '' : '.prod'}.js`),
|
|
||||||
'vue-router': _resolve(`vue-router/dist/vue-router.cjs${ctx.nuxt.options.dev ? '' : '.prod'}.js`),
|
|
||||||
'vue/server-renderer': _resolve('vue/server-renderer'),
|
|
||||||
'vue/compiler-sfc': _resolve('vue/compiler-sfc'),
|
|
||||||
vue: _resolve(`vue/dist/vue.cjs${ctx.nuxt.options.dev ? '' : '.prod'}.js`)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ssr: {
|
ssr: {
|
||||||
external: ctx.nuxt.options.experimental.externalVue
|
external: ['#internal/nitro', '#internal/nitro/utils'],
|
||||||
? ['#internal/nitro', '#internal/nitro/utils', 'vue', 'vue-router']
|
|
||||||
: ['#internal/nitro', '#internal/nitro/utils'],
|
|
||||||
noExternal: [
|
noExternal: [
|
||||||
...transpile({ isServer: true, isDev: ctx.nuxt.options.dev }),
|
...transpile({ isServer: true, isDev: ctx.nuxt.options.dev }),
|
||||||
// TODO: Use externality for production (rollup) build
|
// TODO: Use externality for production (rollup) build
|
||||||
@ -88,7 +75,7 @@ export async function buildServer (ctx: ViteBuildContext) {
|
|||||||
ssr: true,
|
ssr: true,
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
input: { server: entry },
|
input: { server: entry },
|
||||||
external: ['#internal/nitro', ...ctx.nuxt.options.experimental.externalVue ? ['vue', 'vue-router'] : []],
|
external: ['#internal/nitro'],
|
||||||
output: {
|
output: {
|
||||||
entryFileNames: '[name].mjs',
|
entryFileNames: '[name].mjs',
|
||||||
format: 'module',
|
format: 'module',
|
||||||
|
@ -1,41 +1,38 @@
|
|||||||
import { fileURLToPath } from 'node:url'
|
import { fileURLToPath } from 'node:url'
|
||||||
import fsp from 'node:fs/promises'
|
import fsp from 'node:fs/promises'
|
||||||
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
|
import { beforeAll, describe, expect, it } from 'vitest'
|
||||||
import { execaCommand } from 'execa'
|
import { execaCommand } from 'execa'
|
||||||
import { globby } from 'globby'
|
import { globby } from 'globby'
|
||||||
import { join } from 'pathe'
|
import { join } from 'pathe'
|
||||||
|
|
||||||
describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM_CI)('minimal nuxt application', () => {
|
describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM_CI)('minimal nuxt application', () => {
|
||||||
const rootDir = fileURLToPath(new URL('./fixtures/minimal', import.meta.url))
|
const rootDir = fileURLToPath(new URL('./fixtures/minimal', import.meta.url))
|
||||||
const publicDir = join(rootDir, '.output/public')
|
|
||||||
const serverDir = join(rootDir, '.output/server')
|
|
||||||
|
|
||||||
const stats = {
|
|
||||||
client: { totalBytes: 0, files: [] as string[] },
|
|
||||||
server: { totalBytes: 0, files: [] as string[] }
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await execaCommand(`pnpm nuxi build ${rootDir}`)
|
await Promise.all([
|
||||||
|
execaCommand(`pnpm nuxi build ${rootDir}`, { env: { EXTERNAL_VUE: 'false' } }),
|
||||||
|
execaCommand(`pnpm nuxi build ${rootDir}`, { env: { EXTERNAL_VUE: 'true' } })
|
||||||
|
])
|
||||||
}, 120 * 1000)
|
}, 120 * 1000)
|
||||||
|
|
||||||
afterAll(async () => {
|
// Identical behaviour between inline/external vue options as this should only affect the server build
|
||||||
await fsp.writeFile(join(rootDir, '.output/test-stats.json'), JSON.stringify(stats, null, 2))
|
for (const outputDir of ['.output', '.output-inline']) {
|
||||||
})
|
it('default client bundle size', async () => {
|
||||||
|
const clientStats = await analyzeSizes('**/*.js', join(rootDir, outputDir, 'public'))
|
||||||
it('default client bundle size', async () => {
|
expect.soft(roundToKilobytes(clientStats.totalBytes)).toMatchInlineSnapshot('"97.2k"')
|
||||||
stats.client = await analyzeSizes('**/*.js', publicDir)
|
expect(clientStats.files.map(f => f.replace(/\..*\.js/, '.js'))).toMatchInlineSnapshot(`
|
||||||
expect.soft(roundToKilobytes(stats.client.totalBytes)).toMatchInlineSnapshot('"97.2k"')
|
[
|
||||||
expect(stats.client.files.map(f => f.replace(/\..*\.js/, '.js'))).toMatchInlineSnapshot(`
|
"_nuxt/entry.js",
|
||||||
[
|
]
|
||||||
"_nuxt/entry.js",
|
`)
|
||||||
]
|
})
|
||||||
`)
|
}
|
||||||
})
|
|
||||||
|
|
||||||
it('default server bundle size', async () => {
|
it('default server bundle size', async () => {
|
||||||
stats.server = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
|
const serverDir = join(rootDir, '.output/server')
|
||||||
expect.soft(roundToKilobytes(stats.server.totalBytes)).toMatchInlineSnapshot('"63.9k"')
|
|
||||||
|
const serverStats = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
|
||||||
|
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot('"63.9k"')
|
||||||
|
|
||||||
const modules = await analyzeSizes('node_modules/**/*', serverDir)
|
const modules = await analyzeSizes('node_modules/**/*', serverDir)
|
||||||
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot('"2329k"')
|
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot('"2329k"')
|
||||||
@ -90,6 +87,53 @@ describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM
|
|||||||
]
|
]
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('default server bundle size (inlined vue modules)', async () => {
|
||||||
|
const serverDir = join(rootDir, '.output-inline/server')
|
||||||
|
|
||||||
|
const serverStats = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
|
||||||
|
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot('"370k"')
|
||||||
|
|
||||||
|
const modules = await analyzeSizes('node_modules/**/*', serverDir)
|
||||||
|
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot('"590k"')
|
||||||
|
|
||||||
|
const packages = modules.files
|
||||||
|
.filter(m => m.endsWith('package.json'))
|
||||||
|
.map(m => m.replace('/package.json', '').replace('node_modules/', ''))
|
||||||
|
.sort()
|
||||||
|
expect(packages).toMatchInlineSnapshot(`
|
||||||
|
[
|
||||||
|
"@unhead/dom",
|
||||||
|
"@unhead/shared",
|
||||||
|
"@unhead/ssr",
|
||||||
|
"cookie-es",
|
||||||
|
"debug",
|
||||||
|
"defu",
|
||||||
|
"destr",
|
||||||
|
"devalue",
|
||||||
|
"h3",
|
||||||
|
"has-flag",
|
||||||
|
"hookable",
|
||||||
|
"http-graceful-shutdown",
|
||||||
|
"iron-webcrypto",
|
||||||
|
"klona",
|
||||||
|
"ms",
|
||||||
|
"node-fetch-native",
|
||||||
|
"ofetch",
|
||||||
|
"ohash",
|
||||||
|
"pathe",
|
||||||
|
"radix3",
|
||||||
|
"scule",
|
||||||
|
"supports-color",
|
||||||
|
"ufo",
|
||||||
|
"uncrypto",
|
||||||
|
"unctx",
|
||||||
|
"unenv",
|
||||||
|
"unhead",
|
||||||
|
"unstorage",
|
||||||
|
]
|
||||||
|
`)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
async function analyzeSizes (pattern: string | string[], rootDir: string) {
|
async function analyzeSizes (pattern: string | string[], rootDir: string) {
|
||||||
|
11
test/fixtures/minimal/nuxt.config.ts
vendored
11
test/fixtures/minimal/nuxt.config.ts
vendored
@ -1,3 +1,14 @@
|
|||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
|
|
||||||
|
const testWithInlineVue = process.env.EXTERNAL_VUE === 'false'
|
||||||
|
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
|
experimental: {
|
||||||
|
externalVue: !testWithInlineVue
|
||||||
|
},
|
||||||
|
buildDir: testWithInlineVue ? '.nuxt-inline' : '.nuxt',
|
||||||
|
nitro: {
|
||||||
|
output: { dir: fileURLToPath(new URL(testWithInlineVue ? './.output-inline' : './.output', import.meta.url)) }
|
||||||
|
},
|
||||||
sourcemap: false
|
sourcemap: false
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user