Skip to content

[Chore] Eliminate blockchain vendors from landing page initial load #1124

@Sharqiewicz

Description

@Sharqiewicz

User Story

As a first-time visitor to the Vortex landing page
I want the page to load and animate quickly
So that I get a smooth first impression of the product without waiting for blockchain infrastructure I haven't asked for yet


Acceptance Criteria

  • Landing page initial JS payload is ≤ 400 kB gzip (entry chunk + all eagerly-loaded chunks combined)
  • No static import chain from main.tsx reaches wagmi, @polkadot, stellar-sdk, @walletconnect, or @reown at build time — verified via bundle analyser (rollup-plugin-visualizer is already configured in vite.config.ts)
  • @vortexfi/shared browser export resolves to a pre-built ESM artifact, not raw TypeScript source (./src/index.ts)
  • Landing page animations are visually smooth on a simulated mid-tier mobile device (Chrome DevTools 4× CPU throttle, no jank on hero section)

Additional Context

Size: M

Findings

The landing page currently eagerly loads ~7 MB of blockchain vendor code (wagmi, @walletconnect, @polkadot, stellar-sdk) on every visit, including users who never open the widget. This causes sluggish initial render and janky hero animations.

Investigation revealed five root causes:

  1. manualChunks makes vendor-evm a shared runtime host. Splitting vendors by package name forces Rollup to assign any internally-shared utility to the matched vendor chunk. Every marketing page route ends up with a static import to vendor-evm at build time — including components like AnimatedTitle — even though they have no real wagmi dependency in source. This is a Rollup artifact of the chunking strategy, not a source-level problem.

  2. manualChunks increases total size vs the original monolith. Before chunking, Rollup deduplicated everything once. Named chunks introduce cross-chunk import overhead and prevent deduplication, making total bytes larger than the original 8 MB bundle.

  3. @vortexfi/shared resolves to raw TypeScript source. The browser export condition in packages/shared/package.json points to ./src/index.ts — a full export * barrel that includes services/ (polkadot, stellar, wagmi helpers). Even with sideEffects: false, the barrel is too wide for Rollup to tree-shake effectively when used from the landing page.

  4. services/api/index.ts is an unguarded barrel. It re-exports moonbeam.service, polkadot.service, and pendulum.service. Any landing page component that imports from this barrel (e.g. useFeeComparisonDataPriceService) transitively pulls in wagmi and polkadot.

  5. The lazy boundary is on the React component, not the module graph. widget.lazy.tsx defers the component render but the heavy vendor transitive deps remain statically reachable from the entry chunk via shared Rollup intermediate chunks.

Hints

  • FeeComparison on the landing page imports useNetwork (→ contexts/networkwagmi) and useEventsContext (→ contexts/events → same chain). These should be removed — FeeComparison only needs EVM rates and has no real dependency on wallet state.
  • useFeeComparisonData imports PriceService via the services/api barrel. Changing it to import directly from services/api/price.service severs the polkadot/moonbeam chain for that component.
  • packages/shared/package.json should have "sideEffects": false to allow Rollup to tree-shake the barrel. Combined with pointing browser to ./dist/browser/index.js (pre-built ESM), this should eliminate the raw source barrel problem.
  • rollup-plugin-visualizer is already configured in vite.config.ts — use it after each change to verify the import graph.

Desired Approach

  1. Remove manualChunks entirely from vite.config.ts. Let Rollup manage chunking automatically once the module graph is clean.
  2. Audit the static import graph from main.tsx — trace every path that reaches wagmi, @polkadot, stellar-sdk, @walletconnect, or @reown and cut each one.
  3. Sever context imports from marketing components — no file outside widget.lazy.tsx and its descendants should import useNetwork, useEventsContext, or any hook that chains to a blockchain SDK.
  4. Replace barrel imports with direct imports in any file reachable from the landing page (e.g. services/api/price.service instead of services/api).
  5. Fix @vortexfi/shared browser export — point it to ./dist/browser/index.js and add "sideEffects": false. Rebuild shared before testing the frontend.
  6. Validate with the bundle analyser — the landing page preload manifest should list zero chunks that transitively import a blockchain vendor.

Affected surfaces (per CONTEXT.md): Initial bundle tier, widget.lazy.tsx boundary, MarketingLayout, FeeComparison section, @vortexfi/shared package exports.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions