Repository navigation
Bundle size of Vue Router 4 lib became larger than Vue Router 3 lib #1937
Replies: 2 comments 1 reply
|
I think you are not treeshaking your libraries. Maybe not minifying them. You should indeed see a smaller size with Vue Router 4 |
|
posva's quick "you're not tree-shaking" answer is correct in spirit but wrong in detail, because the bundles you screenshotted include a tree-shaken build. The real reason Vue Router 4 is larger than Vue Router 3, and the precise fix:
Vue Router 3 was written for Vue 2 and used Vue 2's option-API reactivity (Object.defineProperty). Vue Router 4 is written for Vue 3 and uses the new Proxy-based reactivity. The router internals are more general-purpose now (handling async loaders, Suspense, custom blocks, navigation guards typed via TS), and that generality costs bytes. There is no version 4 trick that brings it back to Vue Router 3 sizes because the architecture is genuinely larger.
// Bad: pulls in the entire router module
import * as Router from 'vue-router'
const router = Router.createRouter({ ... })// Good: tree-shakes correctly
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({ ... })Your snippet imports only
# In your compiled output, search for the marker strings:
grep -E 'createWebHashHistory|createMemoryHistory|createWebHistory|createRouterMatcher' dist/assets/*.jsIf you see all four, all of them are bundled. That is unexpected and indicates the bundler is including the entire vue-router module.
If your routes have side-effecting route guards or meta computation that touches Pinia/Vuex stores at module-init time, the bundler keeps those stores in the chunk that includes the router. The fix: // router/index.ts
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'
import { useAuthStore } from '@/stores/auth'
const routes: RouteRecordRaw[] = [
{ path: '/', component: () => import('@/views/Home.vue') },
{
path: '/profile',
component: () => import('@/views/Profile.vue'),
meta: { requiresAuth: true },
},
]
export const router = createRouter({
history: createWebHistory(),
routes,
})
// Move store-dependent guards into a separate plugin so the router
// itself doesn't import the store at module-init time.
router.beforeEach(async (to) => {
const auth = useAuthStore() // imported here, not at top
return auth.check(to)
})If you move the store import inside the guard callback, the store's bundle is no longer reachable from the router chunk. This typically shaves another 1-3KB.
If you import vue-router from a path that Vite cannot pre-bundle, the dev path and build path take different resolution routes and you see one size in dev and a different one in production. Verify by: ls -la node_modules/.vite/deps/vue-router.jsIf that file exists, pre-bundling ran. If not, Vite did not pre-bundle vue-router. To force it: // vite.config.ts
export default defineConfig({
optimizeDeps: {
include: ['vue-router'],
},
})
If you are measuring the bundle via webpack-bundle-analyzer or rollup-plugin-visualizer and you have source maps inline (e.g., via build.sourcemap: 'inline'), the reported size includes the original source. Source maps for vue-router are large because the source is TypeScript-heavy. Compare apples to apples: export default defineConfig({
build: {
sourcemap: false, // for the size measurement
rollupOptions: {
output: {
// Strip the .map files from the dist folder before measuring
},
},
},
})With sourcemap: false and the same tree-shaken named imports, your Vue Router 4 contribution should be ~9KB gzipped, which is the published figure. If after all of these checks your Vue Router contribution is still 15+ KB gzipped, please share the output of: npx vite-bundle-visualizerThe visualizer's output will show which export from vue-router is dominating the chunk. Almost always it is one of: Cross-references:
|
Uh oh!
There was an error while loading. Please reload this page.
Hello everyone,

I moved my project from Vue2 to Vue3 and as you can see from screenshots Vue Router bundle size increased.
Vue3:
Vue2:

Is it correct or may be I do something wrong?
How I use Vue Router:
import { createWebHistory } from 'vue-router'import { createRouter } from 'vue-router'If you need any additional details I will provide them.
All reactions