web3modal icon indicating copy to clipboard operation
web3modal copied to clipboard

feat: defer initialization calls until modal is opened. Add loading skeleton

Open tomiir opened this issue 3 months ago • 9 comments

Summary

Defers all AppKit initialization network requests until the modal is actually opened, eliminating HTTP requests on page load. While initialization runs, the modal shows a fast-loading shimmer skeleton so the UI remains responsive. This improves page performance and perceived responsiveness without changing user-facing flows. See compare view for full diff: reown-com/appkit: tomas/apkt-4148-remove-all-http-requests-from-page-load.

Motivation

  • Reduce page-load cost and remove unsolicited background calls.
  • Improve Core Web Vitals by deferring non-critical work.
  • Maintain a smooth UX with immediate visual feedback when users open the modal.

What’s Changed

  • Modal initialization is now lazy:
    • Defers API/metadata fetches and provider probing until the first modal open.
    • Renders a shimmer skeleton instantly while data loads.
  • Error utilities consolidated:
    • Moved ErrorUtil from @reown/appkit-utils into controllers’ utils to be closer to call sites and avoid utils-level coupling.
  • UI updates:
    • w3m modal and related views use wui-shimmer placeholders during initialization.
    • Connecting and email login views updated to avoid preloading network work.
  • Adapters:
    • Wagmi and Solana adapters no longer trigger eager initialization on page load.
  • Tests:
    • Updated to reflect lazy init behavior and skeleton rendering.

Notable Files (high level)

  • App init and gating: @reown/appkit client (packages/appkit/src/client/appkit*.ts)
  • Controllers: ApiController, ModalController lazy init gates
  • UI: packages/scaffold-ui/src/modal/w3m-modal and views use wui-shimmer
  • Adapters: wagmi/AuthConnector, solana/client stop eager work
  • Utilities: ErrorUtil moved to packages/controllers/src/utils/ErrorUtil.ts with export updates

Before vs After

  • Before: AppKit performed HTTP requests during page load.
  • After: No HTTP requests on page load. First open of the modal triggers initialization; users see a shimmer skeleton while data loads. Subsequent opens are fast due to cached state.

Developer Impact

  • Public API: No intended breaking changes.
  • Import note (internal): If anything imported ErrorUtil from @reown/appkit-utils, update to use @reown/appkit-controllers/utils.

How to Test

  • Verify no network calls on page load:
    • Open DevTools Network tab, hard-refresh; expect 0 AppKit HTTP requests before user interaction.
  • Open the modal:
    • Expect shimmer skeleton to render immediately.
    • Data populates as soon as initialization completes.
  • Repeat open:
    • Modal should open without shimmer (warm state) or very briefly with faster resolution.
  • Re-run unit tests:
    • pnpm test should pass across updated packages.
  • Sanity-check flows:
    • Email/social login views still function; skeleton appears during their initial connect states.

Performance/UX Expectations

  • Reduced main-thread and network activity during initial load.
  • Better First Input Delay/Interaction to Next Paint by deferring non-critical work.
  • Immediate visual feedback via shimmer reduces perceived wait time.

Risks and Mitigations

  • Risk: Any logic still relying on eager initialization may fail on first open.
    • Mitigation: Controllers gate actions until init completes; tests updated.
  • Risk: Adapters that assumed pre-initialized providers.
    • Mitigation: Adjusted Wagmi/Solana paths to lazily setup; covered by tests.

Follow-ups

  • Consider idle-time prefetch after first user interaction (not page load).
  • Instrument timing to measure shimmer duration and init latency across environments.

Related

  • APKT-4148: Remove all HTTP requests from page load

  • Compare diff: GitHub compare view

  • Key changes:

    • Deferred initialization across @reown/appkit client, ApiController, ModalController.
    • Shimmer skeleton added to w3m modal/views via wui-shimmer.
    • Eager adapter work removed (Wagmi/Solana).
    • ErrorUtil relocated to controllers’ utils; exports updated.
    • Tests updated to reflect lazy init and skeleton rendering.

Type of change

  • [ ] Chore (non-breaking change that addresses non-functional tasks, maintenance, or code quality improvements)
  • [ ] Bug fix (non-breaking change which fixes an issue)
  • [x] New feature (non-breaking change which adds functionality)
  • [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)

Associated Issues

Closes APKT-4148

Showcase (Optional)

https://github.com/user-attachments/assets/6efcea72-dbb3-4ddd-87d1-c2f59ac75d55

Checklist

  • [ ] Code in this PR is covered by automated tests (Unit tests, E2E tests) => wip
  • [x] My changes generate no new warnings
  • [x] I have reviewed my own code
  • [x] I have filled out all required sections
  • [x] I have tested my changes on the preview link
  • [ ] Approver of this PR confirms that the changes are tested on the preview link

[!NOTE] Defers initialization/config fetches until the modal opens, shows a shimmer loading state during validation, and relocates ErrorUtil to controllers with corresponding controller/UI/adapter/test updates.

  • Core/Controllers:
    • Defer project/config/usage/origin validation to ModalController.open() via ApiController.validateProjectConfig(); add state.validating/validatedConfig and checkAllowedOrigins.
    • Stop eager remote config/origin checks in client; remove AppKit client origin-check path and onramp/SIWX setup from init.
    • Update OptionsController state (add featureOverride, basic) and keep remote features/pay gating; export ConfigUtil/ErrorUtil from controllers utils.
    • ConfigUtil.fetchRemoteFeatures() now reads from OptionsController.state (no params) and warns via inline message.
  • UI:
    • Add shimmer loading to w3m-connect-view while ApiController.state.validating; subscribe to validation state.
    • w3m-modal: remove analytics prefetch on load; retain prefetch on open/embedded flow.
    • wui-flex: make padding a non-attribute prop to support array values.
  • Auth/Adapters:
    • Create auth provider after remote features on modal open; avoid eager auth setup.
    • Update Solana/Wagmi adapters to import ErrorUtil from @reown/appkit-controllers/utils.
  • Utils/Errors:
    • Move ErrorUtil from @reown/appkit-utils to @reown/appkit-controllers/utils; adjust imports across packages.
  • Tests:
    • Update tests to reflect lazy init, validation-on-open, shimmer loading, and new utils paths.
  • Version/Meta:
    • Bump @reown/appkit to 1.8.11.
    • Changeset: patch releases across affected packages.

Written by Cursor Bugbot for commit 7eefa0e1a96369d1d09d11fa835468abaae0d841. This will update automatically on new commits. Configure here.

tomiir avatar Oct 29 '25 11:10 tomiir

🦋 Changeset detected

Latest commit: 7eefa0e1a96369d1d09d11fa835468abaae0d841

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

This PR includes changesets to release 24 packages
Name Type
@reown/appkit-adapter-solana Patch
@reown/appkit-adapter-wagmi Patch
@reown/appkit-utils Patch
@reown/appkit-controllers Patch
@reown/appkit-scaffold-ui Patch
@reown/appkit Patch
@reown/appkit-ui Patch
@reown/appkit-cdn Patch
@reown/appkit-adapter-bitcoin Patch
@reown/appkit-adapter-ethers Patch
@reown/appkit-adapter-ethers5 Patch
@reown/appkit-siwe Patch
@reown/appkit-siwx Patch
@reown/appkit-wallet-button Patch
@reown/appkit-experimental Patch
@reown/appkit-pay Patch
@reown/appkit-core Patch
@reown/appkit-universal-connector Patch
@reown/appkit-testing Patch
@reown/appkit-common Patch
@reown/appkit-polyfills Patch
@reown/appkit-wallet Patch
@reown/appkit-cli Patch
@reown/appkit-codemod 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

changeset-bot[bot] avatar Oct 29 '25 11:10 changeset-bot[bot]

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

Project Deployment Preview Comments Updated (UTC)
appkit-basic-html Ready Ready Preview Comment Oct 29, 2025 0:43am
appkit-demo Canceled Canceled Oct 29, 2025 0:43am
appkit-gallery Canceled Canceled Comment Oct 29, 2025 0:43am
appkit-laboratory Error Error Oct 29, 2025 0:43am
10 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
appkit-basic-example Ignored Ignored Oct 29, 2025 0:43am
appkit-basic-sign-client-example Ignored Ignored Oct 29, 2025 0:43am
appkit-basic-up-example Ignored Ignored Oct 29, 2025 0:43am
appkit-ethers5-bera Ignored Ignored Oct 29, 2025 0:43am
appkit-nansen-demo Ignored Ignored Oct 29, 2025 0:43am
appkit-vue-solana Ignored Ignored Oct 29, 2025 0:43am
appkit-wagmi-cdn-example Ignored Ignored Oct 29, 2025 0:43am
ethereum-provider-wagmi-example Ignored Ignored Oct 29, 2025 0:43am
next-wagmi-solana-bitcoin-example Ignored Ignored Oct 29, 2025 0:43am
vue-wagmi-example Ignored Ignored Oct 29, 2025 0:43am

vercel[bot] avatar Oct 29 '25 11:10 vercel[bot]

Visual Regression Test Results ✅ Passed

✨ No visual changes detected

Chromatic Build: https://www.chromatic.com/build?appId=6493191bf4b10fed8ca7353f&number=253 Storybook Preview: https://6493191bf4b10fed8ca7353f-gfvraznaun.chromatic.com/

github-actions[bot] avatar Oct 29 '25 11:10 github-actions[bot]

📦 Bundle Size Check

Some bundles exceed size limits

📊 View detailed bundle sizes

> @reown/[email protected] size /home/runner/work/appkit/appkit


> size-limit

@reown/appkit - Main Entry
Size limit:   80 kB
Size:         75.17 kB with all dependencies, minified and gzipped
Loading time: 1.5 s    on slow 3G
Running time: 482 ms   on Snapdragon 410
Total time:   2 s
@reown/appkit/react
Package size limit has exceeded by 915 B
Size limit:   230 kB
Size:         230.91 kB with all dependencies, minified and gzipped
Loading time: 4.6 s     on slow 3G
Running time: 1.2 s     on Snapdragon 410
Total time:   5.7 s
@reown/appkit/vue
Size limit:   80 kB
Size:         75.17 kB with all dependencies, minified and gzipped
Loading time: 1.5 s    on slow 3G
Running time: 734 ms   on Snapdragon 410
Total time:   2.3 s
@reown/appkit-scaffold-ui
Size limit:   220 kB
Size:         217.14 kB with all dependencies, minified and gzipped
Loading time: 4.3 s     on slow 3G
Running time: 564 ms    on Snapdragon 410
Total time:   4.9 s
@reown/appkit-ui
Size limit:   500 kB
Size:         13.15 kB with all dependencies, minified and gzipped
Loading time: 257 ms   on slow 3G
Running time: 62 ms    on Snapdragon 410
Total time:   319 ms
Try to reduce size or increase limit at .size-limit.js

ELIFECYCLE  Command failed with exit code 1.


github-actions[bot] avatar Oct 29 '25 11:10 github-actions[bot]

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 80.37% 36519 / 45435
🔵 Statements 80.37% 36519 / 45435
🔵 Functions 78.68% 3957 / 5029
🔵 Branches 86.37% 8822 / 10214
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/adapters/solana/src/client.ts 73.33% 76.08% 40.54% 73.33% 97-104, 137-140, 143-144, 147-148, 151-152, 155-158, 161-169, 176-177, 187-207, 215-216, 221-227, 252-265, 269-270, 273-274, 282-283, 288-295, 315-328, 351-354, 378-379, 389-390, 409-410, 417-418, 442-443, 447-448, 451-452, 489-493, 517-518, 541-547
packages/adapters/solana/src/tests/mocks/W3mFrameProvider.ts 96.15% 84.61% 75% 96.15% 47, 51
packages/adapters/wagmi/src/connectors/AuthConnector.ts 5.76% 100% 25% 5.76% 54-68, 71-92, 95-142, 145-303
packages/appkit-utils/exports/index.ts 100% 100% 100% 100%
packages/appkit/exports/constants.ts 100% 100% 100% 100%
packages/appkit/src/client/appkit-base-client.ts 72.04% 85.42% 75.32% 72.04% 193-194, 200-201, 204, 213, 261-262, 300-301, 303-304, 309-310, 390-391, 427-433, 504-505, 531-532, 535-536, 545, 579-580, 583, 624-628, 635-636, 639-640, 645-646, 657-680, 689-690, 707-727, 731-752, 755-761, 764-770, 773-779, 782-788, 791-801, 804-810, 813-820, 834-843, 846-852, 855-856, 859-860, 879-880, 903-943, 950-962, 968-995, 998-1008, 1040-1041, 1066-1067, 1072, 1087-1103, 1117, 1121-1129, 1160-1161, 1180-1183, 1187-1188, 1190-1191, 1225-1227, 1231-1252, 1257-1258, 1266-1267, 1269-1270, 1364-1365, 1377-1378, 1383, 1406-1411, 1458, 1479-1480, 1489, 1491-1507, 1512, 1558-1559, 1571-1582, 1628-1641, 1686, 1692-1696, 1717-1732, 1735-1736, 1755-1758, 1794-1813, 1845, 1888-1889, 1895-1921, 2142-2143, 2180-2181, 2184-2185, 2201-2204, 2207-2208, 2228-2229, 2232-2233, 2245-2255, 2275-2276, 2279-2286, 2290-2291, 2305, 2313, 2318, 2323-2342, 2345-2354, 2361-2366, 2384-2385, 2388-2389, 2396-2397, 2436-2437, 2508-2509, 2512-2513, 2516-2519, 2522-2523, 2526-2527, 2530-2531, 2534-2535, 2538-2542, 2551-2560, 2569-2580, 1250, 2325-2346
packages/appkit/src/client/appkit.ts 45.71% 62.76% 82.14% 45.71% 67, 88-91, 95, 102-103, 106, 126-140, 143-150, 153-169, 172-184, 189-199, 208-214, 222-223, 245-281, 284-286, 297-311, 313, 315-334, 336-350, 369-391, 397, 418-419, 423-517, 555, 586-587, 610-612, 620-621, 629-630, 633-634, 636-637, 640-641, 652-653, 656-657, 660-661, 664-665, 668-671, 265-278
packages/controllers/exports/utils.ts 100% 100% 100% 100%
packages/controllers/src/controllers/ApiController.ts 97.17% 96.24% 92.06% 97.17% 130-131, 295-296, 345-348, 360-361, 630, 644, 648, 652
packages/controllers/src/controllers/ModalController.ts 93.27% 93.22% 84.61% 93.27% 67-72, 83, 95
packages/controllers/src/controllers/OptionsController.ts 87.62% 98.41% 54.21% 87.62% 245, 269, 278-279, 331, 335, 393-396, 400-403, 407-410, 414-417, 468, 372, 463
packages/scaffold-ui/src/modal/w3m-modal/index.ts 87.62% 86.53% 100% 87.62% 79-82, 96-97, 107-108, 164-165, 225-233, 272-273, 130-207
packages/scaffold-ui/src/partials/w3m-email-login-widget/index.ts 83.96% 85.29% 91.66% 83.96% 54, 69-71, 135-143, 165-166, 172-173, 189-190, 199-200, 94
packages/scaffold-ui/src/views/w3m-connect-view/index.ts 83.7% 85.04% 89.47% 83.7% 81-83, 86, 94, 115, 167-168, 191-192, 232, 246, 297, 301, 335-336, 339-340, 368-369, 374-398, 408-409, 176-384
packages/scaffold-ui/src/views/w3m-connecting-social-view/index.ts 86.2% 77.77% 100% 86.2% 65, 73-74, 92, 108-113, 166-167, 204-212, 247-252, 263-264
packages/ui/src/layout/wui-flex/index.ts 100% 100% 100% 100%
Generated in workflow #16103 for commit 7eefa0e by the Vitest Coverage Report Action

github-actions[bot] avatar Oct 29 '25 11:10 github-actions[bot]

Warnings
:warning:

🌐 Non-company domain introduced (host: example.com) in packages/controllers/tests/controllers/ApiController.test.ts (line 150): https://example.com

Generated by :no_entry_sign: dangerJS against 7eefa0e1a96369d1d09d11fa835468abaae0d841

github-actions[bot] avatar Oct 29 '25 12:10 github-actions[bot]

Opening the modal looks a bit flashy now (you see the loaders and then immediately you see the wallet options). Could we animate out the loaders and animate in the wallet content, so this is more visually pleasing.

svenvoskamp avatar Oct 29 '25 12:10 svenvoskamp

@tomiir I assume the initializing part is faster now?

arein avatar Oct 29 '25 13:10 arein