Skip to content
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

fix(react): Support lazy-loaded routes and components. #15039

Merged
merged 3 commits into from
Jan 23, 2025

Conversation

onurtemizkan
Copy link
Collaborator

@onurtemizkan onurtemizkan commented Jan 16, 2025

Fixes: #15027

This PR adds support for lazily loaded components and routes inside Suspend on react-router pageloads / navigations.

@onurtemizkan onurtemizkan changed the title fix(react): Wait for lazy-loaded pages on navigation fix(react): Wait for lazy-loaded components on navigation Jan 16, 2025
},
{
element: (
<Suspense fallback={<div>Loading...</div>}>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No strong feelings, this is also fine, but could we possibly add this to an existing e2e test app? Would save a little but of ci/processing time 😅

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add this to react-create-browser-router :)

version,
basename,
// Use requestAnimationFrame to wait for Suspense boundaries to settle
requestAnimationFrame(() => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will slightly skew all timestamps, even if there is no suspense etc. happening, right? As this will realistically add ~20ms or so before handleNavigation() is called.

Not a blocker IMHO, but something to consider. Can we make this smarter (e.g. know when this is lazy?) somehow, possibly...?

version,
basename,
});
}, 100);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

100ms delay seems quite a lot, this will skew stuff pretty considerably, I guess 😬 does that not add 100ms to every navigation duration etc...?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could maybe look into other fields of the RouterState https://github.com/remix-run/react-router/blob/d0e474cf6c521881044c445b4730c1a43aa77679/packages/react-router/lib/router/router.ts#L276

E.g. call handleNavigation when state.navigation !== 'loading'?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, updated with the navigation state checker 👍 I also realized that putting the manual timeout made us lose the inner resource.

Copy link

codecov bot commented Jan 17, 2025

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
689 1 688 299
View the full list of 1 ❄️ flaky tests
tracing/request/fetch/test.ts should create spans for fetch requests

Flake rate in main: 14.29% (Passed 54 times, Failed 9 times)

Stack Traces | 10.1s run time
test.ts:7:11 should create spans for fetch requests

To view more test analytics, go to the Test Analytics Dashboard
📢 Thoughts on this report? Let us know!

});
// Wait for the next render if loading an unsettled route
if (state.navigation.state !== 'idle') {
requestAnimationFrame(() => {
Copy link
Member

@s1gr1d s1gr1d Jan 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, my idea with requestAnimationFrame actually worked - that's nice ✨
Thanks for implementing 🙌

But as Francesco pointed out - we should keep in mind the slight overhead and maybe there's even another way to implement this 🤔 Do we know if a route is lazy?

},
{
element: (
<Suspense fallback={<div>Loading...</div>}>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add this to react-create-browser-router :)

Copy link
Contributor

github-actions bot commented Jan 20, 2025

size-limit report 📦

Path Size % Change Change
@sentry/browser 22.98 KB - -
@sentry/browser - with treeshaking flags 21.64 KB - -
@sentry/browser (incl. Tracing) 35.68 KB - -
@sentry/browser (incl. Tracing, Replay) 72.47 KB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 62.98 KB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 76.72 KB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 88.74 KB - -
@sentry/browser (incl. Feedback) 39.2 KB - -
@sentry/browser (incl. sendFeedback) 27.61 KB - -
@sentry/browser (incl. FeedbackAsync) 32.37 KB - -
@sentry/react 25.66 KB - -
@sentry/react (incl. Tracing) 38.46 KB +0.02% +6 B 🔺
@sentry/vue 27.04 KB - -
@sentry/vue (incl. Tracing) 37.43 KB - -
@sentry/svelte 23.11 KB - -
CDN Bundle 24.36 KB - -
CDN Bundle (incl. Tracing) 36 KB - -
CDN Bundle (incl. Tracing, Replay) 70.65 KB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 75.79 KB - -
CDN Bundle - uncompressed 71.16 KB - -
CDN Bundle (incl. Tracing) - uncompressed 106.82 KB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 217.67 KB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 230.21 KB - -
@sentry/nextjs (client) 38.58 KB - -
@sentry/sveltekit (client) 36.21 KB - -
@sentry/node 161.33 KB - -
@sentry/node - without tracing 97.15 KB - -
@sentry/aws-serverless 111.45 KB - -

View base workflow run

@onurtemizkan onurtemizkan force-pushed the onur/rr-lazy-loaded-pages branch from ea60f3a to 2a8888d Compare January 20, 2025 16:46
@onurtemizkan
Copy link
Collaborator Author

@mydea, @s1gr1d, @chargome - I updated the PR to cover the lazy-loaded Routes too. So the problem was the cross-usage of wrapCreateBrowser and withSentryReactRouterRouting. We were losing the allRoutes context in one another and that was why we were not creating the full parameterized span name.

We're actually updating pageload spans and handling navigations on their render, so we can expect the lazy loading to be finished when we do them.

Still, I think we can keep requestAnimationFrame for non-idle router states when we do it as a secondary safety net. But interestingly, I can't reproduce a case with a non-idle state anymore. Looking at the RR source code, it seems possible.

Copy link
Member

@s1gr1d s1gr1d left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good from my side

@onurtemizkan onurtemizkan changed the title fix(react): Wait for lazy-loaded components on navigation fix(react): Support lazy-loaded routes and components. Jan 21, 2025
Copy link
Member

@mydea mydea left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice, this looks neat - great work!

@s1gr1d s1gr1d merged commit b49c1cc into develop Jan 23, 2025
127 checks passed
@s1gr1d s1gr1d deleted the onur/rr-lazy-loaded-pages branch January 23, 2025 08:43
onurtemizkan added a commit that referenced this pull request Feb 3, 2025
Fixes: #15027

This PR adds support for lazily loaded components and routes inside
`Suspend` on react-router pageloads / navigations.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

React Router browser tracing - Lazy imported routes with suspense start transaction spans with wrong path
4 participants