-
-
Notifications
You must be signed in to change notification settings - Fork 5.3k
fix(nuxt): use fresh route when <NuxtLayout>
first renders
#24673
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
Conversation
|
Codecov ReportAll modified and coverable lines are covered by tests β
Additional details and impacted files@@ Coverage Diff @@
## main #24673 +/- ##
=======================================
Coverage ? 58.65%
=======================================
Files ? 5
Lines ? 861
Branches ? 46
=======================================
Hits ? 505
Misses ? 356
Partials ? 0 β View full report in Codecov by Sentry. |
<NuxtLayout>
first renders
WalkthroughThe changes introduce a refined mechanism for handling route reactivity within the Note β‘οΈ AI Code Reviews for VS Code, Cursor, WindsurfCodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback. Note β‘οΈ Faster reviews with cachingCodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure π Recent review detailsConfiguration used: CodeRabbit UI π Files selected for processing (1)
π§ Files skipped from review as they are similar to previous changes (1)
β° Context from checks skipped due to timeout of 90000ms (3)
β¨ Finishing Touches
π§ͺ Generate Unit Tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. πͺ§ TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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: 1
π§Ή Nitpick comments (4)
packages/nuxt/src/app/components/nuxt-layout.ts (2)
129-133
: Prefer an explicitPropType
over bareFunction
Typing props with the generic
PropType
gives clearer IDE hints and prevents accidental misuse.- isRenderingNewLayout: { - type: Function as unknown as () => (name?: string | boolean) => boolean, - required: true, - }, + isRenderingNewLayout: { + type: Object as PropType<(name?: string | boolean) => boolean>, + required: true, + },
151-163
: Dynamic property-proxy incurs per-navigationdefineProperty
costCreating a fresh object and redefining every property on each navigation can add noticeable overhead when the route object contains many keys. Consider a lighter approach:
- Use
shallowReactive({ _: vueRouterRoute })
and expose a single computed getter, or- Cache the proxied object per layout instance and only swap the underlying source reference instead of re-defining descriptors.
Not urgent, but worthwhile for high-traffic apps.
test/nuxt/nuxt-layout.test.ts (1)
95-97
: Avoiddelete
for performance β mutate insteadStatic analysis flags
delete layouts.test
. Setting the entry toundefined
(or callingrouter.removeRoute
) sidesteps the hidden de-opt.- delete layouts.test + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + // layouts.test = undefined // keeps object shape JIT-friendly + // or, if available: + // router.removeRoute('layout-slug')π§° Tools
πͺ Biome (1.9.4)
[error] 96-96: Avoid the delete operator which can impact performance.
Unsafe fix: Use an undefined assignment instead.
(lint/performance/noDelete)
test/bundle.test.ts (1)
120-120
: Consider reducing brittleness of bundle size tests.A strict inline snapshot for bundle size can lead to frequent test churn as the bundle evolves. You may want to use a tolerance or range-based assertion (for example,
expect(bytes).toBeLessThanOrEqual(300 * 1024)
) to make this test more resilient.
π Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
π Files selected for processing (4)
packages/nuxt/src/app/components/nuxt-layout.ts
(6 hunks)test/bundle.test.ts
(1 hunks)test/nuxt/nuxt-layout.test.ts
(1 hunks)test/runtime/app/router.options.ts
(2 hunks)
π§° Additional context used
πͺ Biome (1.9.4)
test/nuxt/nuxt-layout.test.ts
[error] 96-96: Avoid the delete operator which can impact performance.
Unsafe fix: Use an undefined assignment instead.
(lint/performance/noDelete)
β° Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: lint-docs
- GitHub Check: build
- GitHub Check: code
π Additional comments (3)
test/runtime/app/router.options.ts (1)
12-13
: Return value now explicit β good defensive changeRendering a simple
<div>
with the help ofh()
avoids the previous βemptyβrenderβ edge-case where some test runners choke on falsy VNodes. The additional import ofh
completes the change.test/nuxt/nuxt-layout.test.ts (1)
13-14
:useRouter()
relies on auto-imports β add explicit import to avoid fragile testsIn the test environment auto-imports are sometimes disabled, causing
useRouter
to beundefined
. Importing it directly prevents silent failures:-import { useRoute } from '#app/composables/router' +import { useRoute, useRouter } from '#app/composables/router'test/bundle.test.ts (1)
120-120
: Approve updated snapshot for new server bundle size.The inline snapshot expectation has been updated from
"282k"
to"283k"
to reflect the increase in the server bundle size introduced by recent layout and routing changes.
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: 0
π§Ή Nitpick comments (2)
packages/nuxt/src/app/components/nuxt-layout.ts (2)
59-59
: Non-null assertions are used safely but consider refining type safetyThe non-null assertions (
!
) are used in a context where the code logic ensures the route is defined, making them safe. However, it might be better to use type guards or default values to avoid the need for assertions.-let layout = unref(props.name) ?? route!.meta.layout as string ?? 'default' +let layout = unref(props.name) ?? (route?.meta.layout as string) ?? 'default' -const transitionProps = route!.meta.layoutTransition ?? defaultLayoutTransition +const transitionProps = route?.meta.layoutTransition ?? defaultLayoutTransitionAlso applies to: 88-88
145-165
: Excellent route proxy implementation for handling fresh routesThe proxy implementation is very well done. It:
- Checks if the component is outside of
<NuxtPage>
- Creates a dynamic proxy for the route that selectively uses either:
- The eager route when rendering a new layout (ensuring fresh data)
- The lazy route otherwise (maintaining compatibility with existing behavior)
- Makes the proxy reactive with
shallowReactive
This addresses the core issue of the PR by ensuring layouts always use fresh route data on first render.
However, I suggest adding a brief comment explaining why
shallowReactive
is used instead ofreactive
. The shallow version will only track changes to the top-level properties of the route, which is sufficient for this use case and more performant.- provide(PageRouteSymbol, shallowReactive(reactiveChildRoute)) + // Using shallowReactive as we only need to track top-level route properties + provide(PageRouteSymbol, shallowReactive(reactiveChildRoute))
π Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
π Files selected for processing (1)
packages/nuxt/src/app/components/nuxt-layout.ts
(6 hunks)
β° Context from checks skipped due to timeout of 90000ms (4)
- GitHub Check: build
- GitHub Check: codeql (javascript-typescript)
- GitHub Check: codeql (actions)
- GitHub Check: code
π Additional comments (5)
packages/nuxt/src/app/components/nuxt-layout.ts (5)
54-56
: Good approach to determining when to use eager routeThe logic to determine when to use the eager route is clear and includes good comments explaining each condition. This approach ensures that
route
is always defined, addressing the issue mentioned in the previous review comments.
84-84
: Good technique for tracking layout changesUsing
lastLayout
to track the previously rendered layout is an effective approach. This allows the component to detect when a layout is being rendered for the first time, which is crucial for the fix.Also applies to: 90-91
103-105
: Well-designed function for detecting new layout renderingThe
isRenderingNewLayout
function provides a clean way to determine if a layout is being rendered for the first time. This is key to ensuring fresh routes on first render.
130-133
: Props properly typed and requiredThe
isRenderingNewLayout
prop is correctly marked as required and has an appropriate type definition. Good practice to ensure the component receives all necessary props.
2-2
: Added necessary import for the route proxy implementationThe addition of
shallowReactive
to the imports is needed for the reactive route proxy. Good practice to keep imports organized.
@nuxt/kit
nuxt
@nuxt/schema
@nuxt/rspack-builder
@nuxt/vite-builder
@nuxt/webpack-builder
commit: |
CodSpeed Performance ReportMerging #24673 will not alter performanceComparing Summary
|
π Linked issue
resolve #24642
β Type of change
π Description
Hi π this PR syncnuxtApp._route
forNuxtLayout
edited:
this PR updated
useRoute()
within layouts to use the vue-router route if the layout is rendering for the first time in a page transitionI've marked two TODOs in the test - these aren't regressions from this PR but issues I spotted and which we could ultimately fix.
π Checklist