diff --git a/packages/nuxt/src/core/nitro.ts b/packages/nuxt/src/core/nitro.ts index 1743ed26a7..4ec5f15bf6 100644 --- a/packages/nuxt/src/core/nitro.ts +++ b/packages/nuxt/src/core/nitro.ts @@ -58,16 +58,26 @@ export async function initNitro (nuxt: Nuxt) { sourcemap: nuxt.options.sourcemap, externals: { inline: [ - ...(nuxt.options.dev ? [] : ['vue', '@vue/', '@nuxt/', nuxt.options.buildDir]), + ...(nuxt.options.dev + ? [] + : [ + ...nuxt.options.experimental.externalVue ? [] : ['vue', '@vue/'], + '@nuxt/', + nuxt.options.buildDir + ]), 'nuxt/dist', 'nuxt3/dist' ] }, alias: { - 'vue/compiler-sfc': 'vue/compiler-sfc', - 'vue/server-renderer': 'vue/server-renderer', - vue: await resolvePath(`vue/dist/vue.cjs${nuxt.options.dev ? '' : '.prod'}.js`), + ...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 'estree-walker': 'unenv/runtime/mock/proxy', '@babel/parser': 'unenv/runtime/mock/proxy', diff --git a/packages/schema/src/config/experimental.ts b/packages/schema/src/config/experimental.ts index 5c02588aba..e80d749b1e 100644 --- a/packages/schema/src/config/experimental.ts +++ b/packages/schema/src/config/experimental.ts @@ -17,6 +17,12 @@ export default { * Enable Vue's reactivity transform * @see https://vuejs.org/guide/extras/reactivity-transform.html */ - reactivityTransform: false + reactivityTransform: false, + + /** + * Externalize `vue`, `@vue/*` and `vue-router` when build + * @see https://github.com/nuxt/framework/issues/4084 + */ + externalVue: false } } diff --git a/packages/vite/src/server.ts b/packages/vite/src/server.ts index cf0204d2cd..6f3ce6aa17 100644 --- a/packages/vite/src/server.ts +++ b/packages/vite/src/server.ts @@ -30,16 +30,21 @@ export async function buildServer (ctx: ViteBuildContext) { resolve: { alias: { '#build/plugins': resolve(ctx.nuxt.options.buildDir, 'plugins/server'), - // Alias vue + // Alias vue to ensure we're using the same context in development 'vue/server-renderer': _resolve('vue/server-renderer'), 'vue/compiler-sfc': _resolve('vue/compiler-sfc'), - '@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`), + ...ctx.nuxt.options.experimental.externalVue + ? {} + : { + '@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: _resolve(`vue/dist/vue.cjs${ctx.nuxt.options.dev ? '' : '.prod'}.js`) } }, ssr: { + external: ctx.nuxt.options.experimental.externalVue ? ['#internal/nitro', 'vue', 'vue-router'] : ['#internal/nitro'], noExternal: [ ...ctx.nuxt.options.build.transpile, // TODO: Use externality for production (rollup) build @@ -55,7 +60,7 @@ export async function buildServer (ctx: ViteBuildContext) { outDir: resolve(ctx.nuxt.options.buildDir, 'dist/server'), ssr: ctx.nuxt.options.ssr ?? true, rollupOptions: { - external: ['#internal/nitro'], + external: ['#internal/nitro', ...ctx.nuxt.options.experimental.externalVue ? ['vue', 'vue-router'] : []], output: { entryFileNames: 'server.mjs', preferConst: true,