Skip to content

Comments

fix(clerk-js,ui): Preload component chunks in parallel during mount#7901

Open
jacekradko wants to merge 2 commits intomainfrom
jacek/user-4747-ui-delay-opening-user-menu-and-org-switcher-on-slow-internet
Open

fix(clerk-js,ui): Preload component chunks in parallel during mount#7901
jacekradko wants to merge 2 commits intomainfrom
jacek/user-4747-ui-delay-opening-user-menu-and-org-switcher-on-slow-internet

Conversation

@jacekradko
Copy link
Member

@jacekradko jacekradko commented Feb 21, 2026

Summary

  • Preload component chunks in parallel with the common chunk during mount*() calls, eliminating the sequential download waterfall that caused slow first-render on poor connections
  • Pass preloadHint from all 16 mount* methods to ensureMounted() so the component-specific chunk starts downloading immediately alongside the common chunk
  • Move preloadComponent() outside the first-call guard in ensureMounted() so it fires on every call, not just the first — enabling preloading even when a different component was mounted first
  • Remove the previous keepMounted Popover approach (hidden container rendering) in favor of this simpler chunk preloading strategy

Resolves USER-4747

Testing PR: https://github.com/clerk/dashboard/pull/8496

How it works

Before: mount*() → common chunk downloads → React renders → React.lazy() triggers component chunk download (sequential waterfall)

After: mount*() → common chunk and component chunk download in parallel → React renders → React.lazy() finds module already loaded (no wait)

preloadComponent is idempotent (returns a cached promise on repeat calls), so this is safe to call on every ensureMounted() invocation.

Test plan

  • pnpm build passes
  • pnpm test passes (1616 tests, 111 test files)
  • git diff main --stat shows only intended changes (2 files for preloading + 3 files reverting keepMounted)

Summary by CodeRabbit

  • Refactor
    • Component mounting now triggers targeted preloads earlier and consistently across the UI.
  • Performance
    • Preloads run in parallel with common assets and are cached, reducing first-render latency on slow connections and speeding subsequent mounts.
  • Tests
    • Added a test mock to prevent timer leaks during test teardown.
  • Chores
    • Added a changeset documenting a patch release for the affected packages.

@vercel
Copy link

vercel bot commented Feb 21, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Feb 21, 2026 4:14pm

Request Review

@changeset-bot
Copy link

changeset-bot bot commented Feb 21, 2026

🦋 Changeset detected

Latest commit: c5bd5b2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@clerk/clerk-js Patch
@clerk/ui Patch
@clerk/chrome-extension Patch
@clerk/expo Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@jacekradko
Copy link
Member Author

!snapshot

@clerk-cookie
Copy link
Collaborator

Hey @jacekradko - the snapshot version command generated the following package versions:

Package Version
@clerk/agent-toolkit 0.3.0-snapshot.v20260221025222
@clerk/astro 3.0.0-snapshot.v20260221025222
@clerk/backend 3.0.0-snapshot.v20260221025222
@clerk/chrome-extension 3.0.0-snapshot.v20260221025222
@clerk/clerk-js 6.0.0-snapshot.v20260221025222
@clerk/dev-cli 1.0.0-snapshot.v20260221025222
@clerk/expo 3.0.0-snapshot.v20260221025222
@clerk/expo-passkeys 1.0.0-snapshot.v20260221025222
@clerk/express 2.0.0-snapshot.v20260221025222
@clerk/fastify 2.7.0-snapshot.v20260221025222
@clerk/localizations 4.0.0-snapshot.v20260221025222
@clerk/msw 0.0.1-snapshot.v20260221025222
@clerk/nextjs 7.0.0-snapshot.v20260221025222
@clerk/nuxt 2.0.0-snapshot.v20260221025222
@clerk/react 6.0.0-snapshot.v20260221025222
@clerk/react-router 3.0.0-snapshot.v20260221025222
@clerk/shared 4.0.0-snapshot.v20260221025222
@clerk/tanstack-react-start 1.0.0-snapshot.v20260221025222
@clerk/testing 2.0.0-snapshot.v20260221025222
@clerk/ui 1.0.0-snapshot.v20260221025222
@clerk/upgrade 2.0.0-snapshot.v20260221025222
@clerk/vue 2.0.0-snapshot.v20260221025222

Tip: Use the snippet copy button below to quickly install the required packages.
@clerk/agent-toolkit

npm i @clerk/agent-toolkit@0.3.0-snapshot.v20260221025222 --save-exact

@clerk/astro

npm i @clerk/astro@3.0.0-snapshot.v20260221025222 --save-exact

@clerk/backend

npm i @clerk/backend@3.0.0-snapshot.v20260221025222 --save-exact

@clerk/chrome-extension

npm i @clerk/chrome-extension@3.0.0-snapshot.v20260221025222 --save-exact

@clerk/clerk-js

npm i @clerk/clerk-js@6.0.0-snapshot.v20260221025222 --save-exact

@clerk/dev-cli

npm i @clerk/dev-cli@1.0.0-snapshot.v20260221025222 --save-exact

@clerk/expo

npm i @clerk/expo@3.0.0-snapshot.v20260221025222 --save-exact

@clerk/expo-passkeys

npm i @clerk/expo-passkeys@1.0.0-snapshot.v20260221025222 --save-exact

@clerk/express

npm i @clerk/express@2.0.0-snapshot.v20260221025222 --save-exact

@clerk/fastify

npm i @clerk/fastify@2.7.0-snapshot.v20260221025222 --save-exact

@clerk/localizations

npm i @clerk/localizations@4.0.0-snapshot.v20260221025222 --save-exact

@clerk/msw

npm i @clerk/msw@0.0.1-snapshot.v20260221025222 --save-exact

@clerk/nextjs

npm i @clerk/nextjs@7.0.0-snapshot.v20260221025222 --save-exact

@clerk/nuxt

npm i @clerk/nuxt@2.0.0-snapshot.v20260221025222 --save-exact

@clerk/react

npm i @clerk/react@6.0.0-snapshot.v20260221025222 --save-exact

@clerk/react-router

npm i @clerk/react-router@3.0.0-snapshot.v20260221025222 --save-exact

@clerk/shared

npm i @clerk/shared@4.0.0-snapshot.v20260221025222 --save-exact

@clerk/tanstack-react-start

npm i @clerk/tanstack-react-start@1.0.0-snapshot.v20260221025222 --save-exact

@clerk/testing

npm i @clerk/testing@2.0.0-snapshot.v20260221025222 --save-exact

@clerk/ui

npm i @clerk/ui@1.0.0-snapshot.v20260221025222 --save-exact

@clerk/upgrade

npm i @clerk/upgrade@2.0.0-snapshot.v20260221025222 --save-exact

@clerk/vue

npm i @clerk/vue@2.0.0-snapshot.v20260221025222 --save-exact

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 21, 2026

Open in StackBlitz

@clerk/agent-toolkit

npm i https://pkg.pr.new/@clerk/agent-toolkit@7901

@clerk/astro

npm i https://pkg.pr.new/@clerk/astro@7901

@clerk/backend

npm i https://pkg.pr.new/@clerk/backend@7901

@clerk/chrome-extension

npm i https://pkg.pr.new/@clerk/chrome-extension@7901

@clerk/clerk-js

npm i https://pkg.pr.new/@clerk/clerk-js@7901

@clerk/dev-cli

npm i https://pkg.pr.new/@clerk/dev-cli@7901

@clerk/expo

npm i https://pkg.pr.new/@clerk/expo@7901

@clerk/expo-passkeys

npm i https://pkg.pr.new/@clerk/expo-passkeys@7901

@clerk/express

npm i https://pkg.pr.new/@clerk/express@7901

@clerk/fastify

npm i https://pkg.pr.new/@clerk/fastify@7901

@clerk/hono

npm i https://pkg.pr.new/@clerk/hono@7901

@clerk/localizations

npm i https://pkg.pr.new/@clerk/localizations@7901

@clerk/nextjs

npm i https://pkg.pr.new/@clerk/nextjs@7901

@clerk/nuxt

npm i https://pkg.pr.new/@clerk/nuxt@7901

@clerk/react

npm i https://pkg.pr.new/@clerk/react@7901

@clerk/react-router

npm i https://pkg.pr.new/@clerk/react-router@7901

@clerk/shared

npm i https://pkg.pr.new/@clerk/shared@7901

@clerk/tanstack-react-start

npm i https://pkg.pr.new/@clerk/tanstack-react-start@7901

@clerk/testing

npm i https://pkg.pr.new/@clerk/testing@7901

@clerk/ui

npm i https://pkg.pr.new/@clerk/ui@7901

@clerk/upgrade

npm i https://pkg.pr.new/@clerk/upgrade@7901

@clerk/vue

npm i https://pkg.pr.new/@clerk/vue@7901

commit: cdc7d44

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 21, 2026

📝 Walkthrough

Walkthrough

Calls to ui.ensureMounted() were updated to pass a preloadHint (component name) so component chunks can be preloaded during mount. ensureMounted was changed to invoke the preload earlier and unconditionally when preloadHint is provided; the preload is idempotent. A changeset was added for patch bumps, and a Vitest mock for @formkit/auto-animate/react was introduced in test setup. No public API signatures were changed.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: preloading component chunks in parallel during mount to optimize first-render latency on slow connections.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Replace the keepMounted Popover approach with chunk preloading.
Pass preloadHint to ensureMounted() from all mount methods so component
chunks download in parallel with the common chunk, eliminating the
sequential waterfall on slow connections. Move preloadComponent() call
outside the first-call guard so it fires on every ensureMounted() call.
@jacekradko jacekradko force-pushed the jacek/user-4747-ui-delay-opening-user-menu-and-org-switcher-on-slow-internet branch from 9b06f86 to cdc7d44 Compare February 21, 2026 03:32
The __mocks__ directory in src/elements/ was not detected by Vitest for
node_module mocks, so auto-animate ran in tests and leaked timers that
fired after jsdom teardown, causing requestAnimationFrame errors.
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/clerk-js/vitest.setup.mts`:
- Around line 265-270: Add unit tests that exercise the new preload/mount flow
and assert the component lifecycle now uses the explicit auto-animate mock:
write tests that simulate the preload step and then mount/render the component
and verify expected post-preload behavior (e.g., DOM state, callbacks invoked,
side effects) and that '@formkit/auto-animate/react' is mocked via
useAutoAnimate returning [null]; update or add tests in the clerk-js test suite
to cover both the preload->mount transition and that useAutoAnimate is not
causing timers or animations to run during teardown to prevent regressions.

Comment on lines +265 to +270
// Mock @formkit/auto-animate to prevent timers leaking after test teardown.
// The __mocks__ directory in src/elements/ is not detected by Vitest for
// node_module mocks, so we need an explicit vi.mock here.
vi.mock('@formkit/auto-animate/react', () => ({
useAutoAnimate: () => [null],
}));
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add tests covering the behavioral change introduced in this PR.

No tests were added or updated to cover the new preload/mount behavior and the explicit auto-animate mock. Please add/adjust tests to validate the changed flow and guard against regressions.

As per coding guidelines “If there are no tests added or modified as part of the PR, please suggest that tests be added to cover the changes.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/clerk-js/vitest.setup.mts` around lines 265 - 270, Add unit tests
that exercise the new preload/mount flow and assert the component lifecycle now
uses the explicit auto-animate mock: write tests that simulate the preload step
and then mount/render the component and verify expected post-preload behavior
(e.g., DOM state, callbacks invoked, side effects) and that
'@formkit/auto-animate/react' is mocked via useAutoAnimate returning [null];
update or add tests in the clerk-js test suite to cover both the preload->mount
transition and that useAutoAnimate is not causing timers or animations to run
during teardown to prevent regressions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants