Repository navigation
bundler-webpack: SSR bundle inlines a second Vue runtime -> 'Cannot redefine property' when rendering multiple pages #1718
Description
Describe the bug
When building a VuePress site with @vuepress/bundler-webpack and rendering multiple pages via SSR, the build fails intermittently (only on the 2nd+ page) with:
TypeError: Cannot redefine property: navbar
at Object.defineProperty (<anonymous>)
at useTemplateRef (node_modules/.pnpm/@vue+runtime-core@3.5.41/node_modules/@vue/runtime-core/dist/runtime-core.cjs.prod.js:1255:14)
at setup (app.cjs:57639:52)
...
The error is triggered by useTemplateRef('navbar') in the VPNavbar component of theme-default, but any component that uses useTemplateRef and is rendered on more than one page hits it.
Reproduced in the vuepress/ecosystem monorepo CI (bump branch, webpack e2e / webpack docs build). Only the webpack bundler is affected; the Vite bundler works fine.
Root cause
In packages/bundler-webpack/src/build/createServerConfig.ts, the SSR server bundle only externalizes the exact vue package:
config.externals(['vue'])The array form of webpack externals matches the request exactly, so vue is matched, but the subpath vue/server-renderer is not. SFCs compiled for SSR (by @vue/compiler-sfc) generate import { ... } from 'vue/server-renderer'. Because vue/server-renderer is not externalized, webpack resolves it to the standalone @vue/server-renderer package and inlines it — together with @vue/runtime-dom, @vue/runtime-core and @vue/shared — into the server bundle.
This produces two copies of the Vue runtime inside the SSR bundle:
- Components are instantiated by the inlined
@vue/runtime-core; theirinstance.refsis initialized to the inlined@vue/sharedEMPTY_OBJ. useTemplateRefin componentsetup()comes from the externalizedvue(external@vue/runtime-core), which guards withinstance.refs === EMPTY_OBJusing the externalEMPTY_OBJ.
Because the two EMPTY_OBJ objects differ, the guard if (instance.refs === EMPTY_OBJ) instance.refs = {} never triggers in the production bundle, so useTemplateRef always runs Object.defineProperty(instance.refs, key, { ..., configurable: false }). On the second SSR pass the same key (navbar) already exists as a non-configurable property on the shared refs object → Cannot redefine property: navbar.
This only reproduces in the production build (runtime-core.cjs.prod.js), because the development build of useTemplateRef additionally checks isTemplateRefKey, which masks the issue.
Expected behavior
The server bundle should externalize vue/server-renderer (and the @vue/* runtime packages) so only a single Vue runtime is used — matching the comment already present in the source:
// set externals
// externalize vue in ssr mode, because we need to import `'vue/server-renderer'` in node side
// for ssr usage, then we also need vue as peer-dependency when using pnpm
config.externals(['vue'])Proposed fix
config.externals([
({ request }, callback) => {
if (
request === 'vue' ||
request.startsWith('vue/') ||
request.startsWith('@vue/')
) {
callback(null, `commonjs ${request}`)
} else {
callback()
}
},
])Environment
@vuepress/bundler-webpack: 2.0.0-rc.30vue: 3.5.41- Build target: Node.js SSR server bundle (
app.cjs)
Activity
Mister-Hope commentedon Aug 13, 2026
This is now affecting downstream, probably caused by behavior changes in Vue or Webpack.
Ecosystem encounter this even in rc30.
github-actions commentedon Aug 29, 2026
This issue is marked as
stalebecause it has not had recent activity. Issues marked withstalewill be closed if they have no activity within 7 days.github-actions commentedon Sep 22, 2026
This issue is marked as
stalebecause it has not had recent activity. Issues marked withstalewill be closed if they have no activity within 7 days.Mister-Hope commentedon Sep 22, 2026
.
fix(bundler-webpack): externalize vue subpaths in ssr bundle (close #…