-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
wip: vapor mode #2509
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
base: main
Are you sure you want to change the base?
wip: vapor mode #2509
Conversation
✅ Deploy Preview for vue-router canceled.
|
commit: |
|
Note for myself for refactoring and simplification: Playground |
|
Is this already compatible with “3.6.0-alpha.1”? |
You can try it in [email protected] |
|
The automatic global registration of the virtual DOM |
|
FYI this is planned after #2415 which will also allow to register a custom RouterView and RouterLink |
|
Is this a last blocker of the epic of embedding Vapor into the core? |
|
No |
📝 WalkthroughWalkthroughAdds Vapor-compatible router components (VaporRouterLink, VaporRouterView), new comprehensive Vitest tests and a mount helper, exposes getLinkClass, updates router install to skip global props in Vapor apps, and adjusts monorepo/package dependency pins to an external Vue registry plus several dependency bumps. Changes
Sequence Diagram(s)mermaid Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2509 +/- ##
==========================================
- Coverage 85.32% 84.32% -1.00%
==========================================
Files 84 86 +2
Lines 9769 9935 +166
Branches 2220 2220
==========================================
+ Hits 8335 8378 +43
- Misses 1422 1545 +123
Partials 12 12 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Is there any progress? |
|
It works, You can try it: |
|
Will the next step be to make this available in a beta version tag or will it simply be a new release when vue 3.6 is out of beta? |
|
When using a vapor only app with |
|
The experimental (and future) router already stopped registering those components because of that |
packages/router/vitest.config.ts
Outdated
| resolve: { | ||
| alias: { | ||
| // cjs does not export vapor runtime, use esm instead. | ||
| vue: 'vue/dist/vue.esm-bundler.js', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did you manage to add any test? That would be great to iterate on details
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds experimental Vapor mode support to vue-router by introducing two new components: VaporRouterView and VaporRouterLink. The implementation conditionally disables global properties ($router and $route) in Vapor mode and includes comprehensive test coverage for both components.
Changes:
- Added Vapor-compatible
VaporRouterViewandVaporRouterLinkcomponents with full functionality - Conditionally disabled global properties injection for Vapor apps
- Updated Vue dependency to a pre-release version that includes Vapor support
Reviewed changes
Copilot reviewed 17 out of 18 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| packages/router/src/VaporRouterView.ts | New Vapor-compatible RouterView component implementation |
| packages/router/src/VaporRouterLink.ts | New Vapor-compatible RouterLink component implementation |
| packages/router/src/router.ts | Added conditional check to skip global properties in Vapor mode |
| packages/router/src/RouterLink.ts | Exported getLinkClass function for reuse in VaporRouterLink |
| packages/router/src/index.ts | Exported new Vapor components |
| packages/router/tests/VaporRouterView.spec.ts | Comprehensive test suite for VaporRouterView |
| packages/router/tests/VaporRouterLink.spec.ts | Comprehensive test suite for VaporRouterLink |
| packages/router/tests/mount.ts | Added test mounting utilities for Vapor components |
| packages/router/package.json | Updated dependencies to pre-release versions |
| packages/router/tsconfig.json | Removed Playwright types reference |
| package.json | Added pnpm overrides and new script |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/router/src/router.ts (1)
1013-1025:⚠️ Potential issue | 🟠 MajorTree-shaking concern: components registered unconditionally for Vapor apps.
The global property injection is correctly guarded by
!app.vapor, butRouterLinkandRouterVieware still registered viaapp.component()on lines 1014-1015 regardless of the app type. As noted in PR discussion, this causes Vapor-only apps to pull in the full virtual DOM runtime.Consider extending the vapor check to also skip component registration:
💡 Suggested approach
install(app: App) { - app.component('RouterLink', RouterLink) - app.component('RouterView', RouterView) + if (!app.vapor) { + app.component('RouterLink', RouterLink) + app.component('RouterView', RouterView) + } // TODO: move this part for composition API only if (!app.vapor) {Alternatively, a separate
createVaporRouterentry point could handle Vapor-specific registration as suggested in the PR comments.
🤖 Fix all issues with AI agents
In `@package.json`:
- Around line 68-70: The package entries for "vue", "@vue/runtime-dom", and
"@vue/server-renderer" currently point to pkg.pr.new commit URLs; replace those
URL overrides with proper npm version specifiers (for example "3.6.0-beta.5") or
remove the overrides entirely so package.json uses standard npm versions; update
the three keys ("vue", "@vue/runtime-dom", "@vue/server-renderer") to the chosen
semver strings and run npm install / yarn install to verify dependency
resolution.
In `@packages/router/__tests__/mount.ts`:
- Around line 52-84: The test helper createVaporMount mounts a Vapor app but
never calls app.unmount(), risking leaks; modify createVaporMount so the created
app instance is stored in an outer-scope variable and then call app.unmount() in
the afterEach cleanup before removing the DOM element. Specifically, keep the
existing const app = createVaporApp(...) inside the returned mount function but
also assign it to an outer let mountedApp variable (or return an unmount
function), and ensure afterEach calls mountedApp?.unmount() (and clears
mountedApp) so Vapor lifecycle hooks run and state is not retained between
tests.
In `@packages/router/package.json`:
- Line 153: Remove the "vue" entry from the dependencies block in package.json
(the dependency key "vue": "https://pkg.pr.new/vue@d3fca3b") so the package does
not ship a hard-coded PR URL; leave/ensure "vue" only exists in peerDependencies
and devDependencies (the existing "peerDependencies" and "devDependencies"
entries) to keep Vue as a peer and development-only dependency.
🧹 Nitpick comments (6)
packages/router/src/router.ts (1)
1018-1019: Track type definition forapp.vapor.The
@ts-expect-errorsuppression is reasonable while Vapor is experimental. Once Vue 3.6 stabilizes the Vapor API, ensure theAppinterface is properly augmented to include thevaporproperty, or import the correct types from Vue.packages/router/__tests__/VaporRouterView.spec.ts (1)
300-300: Consider renaming describe block to match component name.The test suite is named
'RouterView'but testsVaporRouterView. For clarity and test output readability, consider renaming to'VaporRouterView'.-describe('RouterView', () => { +describe('VaporRouterView', () => {packages/router/__tests__/VaporRouterLink.spec.ts (4)
15-34: Several Vue imports appear unused in this test file.Many Vapor primitives imported from
vue(e.g.,PropType,VaporDirective,setInsertionState,txt) are used in specific inline component definitions within tests. However, consider verifying all imports are necessary. For instance,createComponentWithFallbackappears on line 953 but some others may be unnecessary.
54-59: Inconsistent aliasOf initialization pattern.Lines 54-58 reassign records with
aliasOfproperties using object spread, while line 59 mutatesrecords.childEmptyAliasdirectly. This inconsistency could cause confusion.♻️ Suggested fix for consistency
records.homeAlias = { aliasOf: records.home } as RouteRecordNormalized records.parentAlias = { aliasOf: records.parent, } as RouteRecordNormalized records.childAlias = { aliasOf: records.child } as RouteRecordNormalized -records.childEmptyAlias.aliasOf = records.childEmpty +records.childEmptyAlias = { aliasOf: records.childEmpty } as RouteRecordNormalized
406-443: Inconsistent prop binding syntax across tests.Some tests use getter functions
{ to: () => locations.basic.string }(line 409), while others pass values directly{ to: locations.basic.string }(line 441). While both patterns may work, this inconsistency could mask issues with reactive vs static prop handling.Consider documenting which pattern is intended for which scenario, or standardizing on one approach for clarity.
1012-1013: Consider adding a brief comment explaining the$evtclickpattern.The
@ts-ignoreon line 1012 suppresses a type error for the Vapor-specific event binding pattern. A brief comment explaining this is Vapor's internal event delegation mechanism would help future maintainers.📝 Suggested documentation
- // `@ts-ignore` - n6.$evtclick = e => slotProps0.navigate(e) + // Vapor's event delegation: $evt{eventname} binds click handler + // `@ts-ignore` - internal Vapor API + n6.$evtclick = e => slotProps0.navigate(e)
| "vue": "https://pkg.pr.new/vue@d3fca3b", | ||
| "@vue/runtime-dom": "https://pkg.pr.new/@vue/runtime-dom@d3fca3b", | ||
| "@vue/server-renderer": "https://pkg.pr.new/@vue/server-renderer@d3fca3b" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
latest Vue 3.6 version npm registry
💡 Result:
Latest Vue 3.6.x published on the npm registry (prerelease) is 3.6.0-beta.5, published Jan 30, 2026. [1]
🏁 Script executed:
# Check if this is a known temporary state and find any related context
cd /dev/null
# First, let's look at the full package.json to understand the broader context
head -100 package.jsonRepository: vuejs/router
Length of output: 2732
Replace pkg.pr.new URLs with proper npm version specifiers before merging.
These pkg.pr.new URLs are appropriate for WIP testing against unreleased Vue 3.6 features, but should not be included in production branches. Vue 3.6.0-beta.5 is now available on npm (published Jan 30, 2026) and can be used instead of the commit-pinned URLs (d3fca3b), or remove these overrides entirely once Vue 3.6 reaches stable release.
🤖 Prompt for AI Agents
In `@package.json` around lines 68 - 70, The package entries for "vue",
"@vue/runtime-dom", and "@vue/server-renderer" currently point to pkg.pr.new
commit URLs; replace those URL overrides with proper npm version specifiers (for
example "3.6.0-beta.5") or remove the overrides entirely so package.json uses
standard npm versions; update the three keys ("vue", "@vue/runtime-dom",
"@vue/server-renderer") to the chosen semver strings and run npm install / yarn
install to verify dependency resolution.
| "tinyglobby": "^0.2.15", | ||
| "unplugin": "^3.0.0", | ||
| "unplugin-utils": "^0.3.1", | ||
| "vue": "https://pkg.pr.new/vue@d3fca3b", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
vue should not be a production dependency.
Having vue in dependencies (line 153) rather than only in devDependencies and peerDependencies is problematic. When this package is published, it would bundle or require a specific Vue build from pkg.pr.new, which is a PR-specific URL that may become unavailable.
For a router library, Vue should only be:
- A
peerDependency(already present at line 195) - A
devDependencyfor development/testing (already present at line 189)
🛠️ Suggested fix
Remove vue from the dependencies block:
"dependencies": {
"@babel/generator": "^7.28.6",
"@vue-macros/common": "^3.1.1",
"@vue/devtools-api": "^8.0.6",
"ast-walker-scope": "^0.8.3",
"chokidar": "^5.0.0",
"json5": "^2.2.3",
"local-pkg": "^1.1.2",
"magic-string": "^0.30.21",
"mlly": "^1.8.0",
"muggle-string": "^0.4.1",
"pathe": "^2.0.3",
"picomatch": "^4.0.3",
"scule": "^1.3.0",
"tinyglobby": "^0.2.15",
"unplugin": "^3.0.0",
"unplugin-utils": "^0.3.1",
- "vue": "https://pkg.pr.new/vue@d3fca3b",
"yaml": "^2.8.2"
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "vue": "https://pkg.pr.new/vue@d3fca3b", | |
| "dependencies": { | |
| "@babel/generator": "^7.28.6", | |
| "@vue-macros/common": "^3.1.1", | |
| "@vue/devtools-api": "^8.0.6", | |
| "ast-walker-scope": "^0.8.3", | |
| "chokidar": "^5.0.0", | |
| "json5": "^2.2.3", | |
| "local-pkg": "^1.1.2", | |
| "magic-string": "^0.30.21", | |
| "mlly": "^1.8.0", | |
| "muggle-string": "^0.4.1", | |
| "pathe": "^2.0.3", | |
| "picomatch": "^4.0.3", | |
| "scule": "^1.3.0", | |
| "tinyglobby": "^0.2.15", | |
| "unplugin": "^3.0.0", | |
| "unplugin-utils": "^0.3.1", | |
| "yaml": "^2.8.2" | |
| }, |
🤖 Prompt for AI Agents
In `@packages/router/package.json` at line 153, Remove the "vue" entry from the
dependencies block in package.json (the dependency key "vue":
"https://pkg.pr.new/vue@d3fca3b") so the package does not ship a hard-coded PR
URL; leave/ensure "vue" only exists in peerDependencies and devDependencies (the
existing "peerDependencies" and "devDependencies" entries) to keep Vue as a peer
and development-only dependency.
Description
This PR provide two vapor components:
VaporRouterViewandVaporRouterLink.I'm not sure whether we should provide a
vue-router/vaporfor users to make migration easier.The access globalProperties warning should be remove.
Playground
https://repl.zmjs.dev/vuejs/vue-router
TODO
Summary by CodeRabbit
New Features
Tests
Chores