perf(wallets): lazy-load chain providers, drop / first-load JS from 2.01 MB to 703 kB#1992
Draft
babkenmes wants to merge 2 commits into
Draft
perf(wallets): lazy-load chain providers, drop / first-load JS from 2.01 MB to 703 kB#1992babkenmes wants to merge 2 commits into
babkenmes wants to merge 2 commits into
Conversation
Move wagmi/viem and connection/transfer/RPC-health modules into a lazy EVMConnectionRegistrar chunk so a static import of @layerswap/wallet-evm no longer pulls them. Legacy createEVMProvider / EVMProvider exports move to ./legacy and retain their eager imports; shared wrapper + WalletConnectConfig context live in shellInternals. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…de chain Suspense Replicates EVM's lazy-registrar split for Starknet, SVM, TON, Fuel, Bitcoin, Tron, and Paradex. Each chain now has shellInternals.tsx (lazy wrapper), XConnectionRegistrar.tsx (heavy SDK chunk), and legacy.tsx (eager createXProvider factory + deprecated singleton). The static index.tsx references the registrar only via dynamic import(), so consumers of createXShell don't pull wagmi / @starknet-react/core / @solana/wallet- adapter-react / @tonconnect/ui-react / @fuels/react / @bigmi/react / @tronweb3/tronwallet-adapter-react-hooks / @paradex/sdk into the critical-path bundle. Result: / First Load JS drops from 2.01 MB → 703 kB. Additional changes so the form is visible from first paint: - New wrapperHostsChildren option on defineWalletProvider. When false, the chain wrapper hosts only the registrar; children render as a sibling outside the lazy Suspense. Set false for all eight chains — no chain Suspense gates the form anymore. - New wagmiConfigStore in @layerswap/wallet-evm publishes the wagmi Config out of the React tree. Paradex's useParadexConnection reads it at call time via getEVMWagmiConfig() instead of useConfig(), so the Paradex registrar no longer needs WagmiProvider as a React ancestor. - Dropped the sync-when-cached wrapper pattern. The if/else swap between <ImplComponent> and <LazyComponent> caused subtree remounts when chunks landed (different component types). React.lazy caches resolved modules itself — using the lazy ref directly keeps component identity stable. - preloadDefaultProviders now warms both the wrapper chunk and the connection-registrar chunk for each chain; DefaultChainShells fires it in a useEffect on mount. Three pnpm overrides added for build-time issues uncovered along the way: - @tanstack/react-query 5.90.11 — was duplicated via @fuels/react, producing "No QueryClient set" at runtime. - rpc-websockets 9.3.2 — newer 9.3.9 transitively pulls uuid@14 (ESM-only), breaking the Next webpack build through @solana/web3.js. - @types/react / @types/react-dom 19.2.3 — Radix sub-deps pulled 18.3.28 types, producing a ReactNode bigint mismatch on Vercel cold builds. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
connectionRegistrar: () => import("./XConnectionRegistrar"). Replicates the EVM split across Starknet, SVM, TON, Fuel, Bitcoin, Tron, Paradex.wrapperHostsChildren: falseoption ondefineWalletProviderrenders the form as a sibling of every chain wrapper instead of nested inside the chain Suspense boundaries — so a slow chain chunk no longer hides the form.useParadexConnectionno longer callsuseConfig()from wagmi. EVM publishes the wagmiConfigvia a side store (wagmiConfigStore); Paradex reads it at call time. Lets Paradex's registrar run outsideWagmiProvider, which was the last cross-chain React-context coupling.Result
//swap/[swapId]grepconfirms the heavy SDK chunks (WagmiProvider,StarknetProvider,TonConnectUIProvider,BigmiProvider,FuelHooksProvider) all end up in async chunks not loaded on/.Architectural changes
Per chain, three new files alongside the slimmed
index.tsx:XConnectionRegistrar.tsx— lazy chunk:useXConnection,useXTransfer, plus any provider classes that statically import a chain SDK (e.g.StarknetNftProvider,SolanaAddressUtilsProvider,TonAddressUtilsProvider,BitcoinGasProvider).shellInternals.tsx— the lazy chain-wrapper component + any cross-file context.legacy.tsx— eagercreateXProviderfactory + the deprecatedXProviderconst initializer, both moved out of the static surface so tree-shaking actually drops them when onlycreateXShellis used.The shell's
index.tsxbecomes a thin re-export surface —export { createXProvider, XProvider } from "./legacy"— and only references the heavy module via() => import("./XConnectionRegistrar").Dropped the
sync-when-cachedwrapper pattern (if (Impl) return <Impl>; else return <Lazy>) — it caused subtree remounts when chunks landed because the rendered component type swapped from the lazy ref to the impl ref. React.lazy caches resolved modules itself; using the lazy ref directly keeps component identity stable.preloadDefaultProviders()now warms both the wrapper chunk and the connection-registrar chunk for every chain, andDefaultChainShellsfires it in auseEffecton mount so chunks arrive in parallel with hydration.Pnpm overrides
Three version pins were needed for clean builds:
@tanstack/react-query: 5.90.11—@fuels/reactpulled5.90.16in parallel, producing a "No QueryClient set" runtime error from two distinctQueryClientContextinstances.rpc-websockets: 9.3.2— newer9.3.9transitively requiresuuid@14(ESM-only), breaking webpack through@solana/web3.js.@types/react: 19.2.3/@types/react-dom: 19.2.3— Radix sub-deps pulled@types/react@18.3.28, producing aReactNodebigintmismatch inAddressWithIcon.tsxon Vercel cold builds.Test plan
pnpm install— single version of@types/react,@tanstack/react-query,rpc-websocketsinnode_modules/.pnpmpnpm -r build— every wallet package + widget compilespnpm --filter @layerswap/bridge build— bridge build green;/First Load JS reads ~700 kBWagmiProvider,StarknetProvider, etc.) are not in/'s chunk listgetEVMWagmiConfig) — verify connect + authorize still works@types/reacttype mismatch)🤖 Generated with Claude Code