First Screen Render Optimization

After code injection completes, the miniapp enters the first screen render phase: Page.onLoad fires, the component tree initializes, initial data is transferred to the view layer, the view layer renders, and the process ends when Page.onReady fires.

Time cost in this phase comes from two directions: rendering complexity (node count, data size) and data wait time (network requests, local reads). Both affect when users see usable content.

Slim Down Initial Data

Data in data is transferred from the logic layer to the view layer before each render. The size of the initial data directly affects transfer time and render time.

  • Unused first-screen data: Data for pagination, tab content, or dialogs that aren't shown on the first screen should not be in data initially — they will still participate in data transfer and render computation. Set them via setData only when needed.
  • Non-render data in data: Intermediate computation results, config objects, and static lookup tables that have nothing to do with the view should not be in data. Store them on this as regular properties instead.

Reduce First-Screen Node Count

More nodes on the page means more layout computation and drawing overhead in the view layer.

Common strategies:

  • Conditional rendering with delay: Off-screen areas (collapsed content, bottom sections) can be rendered after the first screen completes
  • Paginated list rendering: Only render the first few items on the first screen; append more as the user scrolls
  • Defer non-essential component mounts: Too many custom components increase initialization overhead; components not needed on the first screen can be mounted lazily

Use Local Cache

For first-screen data that doesn't change frequently, use a "render from cache first, update in background" strategy. The miniapp provides setStorage and getStorage for local caching; local data returns much faster than network requests.

  1. Write to local cache after a successful request
  2. On next startup, render from cache first
  3. Simultaneously fetch fresh data in the background
  4. Update the view when data returns
import { getStorage, setStorage } from '@ray-js/ray';

function HomePage() {
  const [data, setData] = useState(null);

  useEffect(() => {
    // Render from cache first
    getStorage({
      key: 'panelData',
      success: (res) => setData(res.data),
    });

    // Fetch fresh data in background
    fetchPanelData().then((fresh) => {
      setData(fresh);
      setStorage({ key: 'panelData', data: fresh });
    });
  }, []);
}

Use Skeleton Screen

Even with caching, some data still requires waiting. A skeleton screen displays the rough layout of the page before data arrives, letting users perceive that the page is loading rather than unresponsive, reducing perceived wait time.

See Skeleton Screen.

Miniapp Preloading

For miniapps opened via cards or shortcut entries, call preDownloadMiniApp and preloadPanel to pre-download the package in the background. When the user taps, the download phase is skipped and the flow goes directly to injection, noticeably improving first-open experience. Default home page cards have built-in pre-download logic — no additional configuration needed.

Best for: Home page cards that launch a miniapp on tap. Default cards pre-download miniapp assets so users go directly to launch on tap.

Use Memory Cache

When a miniapp is re-entered shortly after closing, the base library memory cache mechanism can skip download and some injection steps, speeding up re-entry. This is enabled by default; don't disable it unless there is a specific reason.

See Memory Cache.

Checklist

SymptomPossible CauseOptimization
Long first-screen render timeInitial data includes non-first-screen fields; too much data transferredKeep only fields needed for first-screen render; load other data on demand or lazily
Slow layout calculation, rendering lagToo many nodes on first screenUse conditional rendering or paginated rendering for collapsed areas and lists; only render visible content on first screen
First-screen content waits for networkEvery startup depends on network response before renderingFor infrequently changing data, render from local cache first, then update view with background request
Long perceived blank screenNo content shown during data loadingAdd skeleton screen to display page outline before data arrives
Slow first open after card tapPackage download only starts when tappedCall preDownloadMiniApp / preloadPanel to pre-download in background
Noticeably slower second openMemory cache has been disabledConfirm memory cache is not disabled; restore default configuration