Awesome-omni-skill solid-router-preloading

Solid Router preloading: preload function for routes, usePreloadRoute hook, hover/focus intent detection, lazy component preloading, performance optimization.

install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/frontend/solid-router-preloading" ~/.claude/skills/diegosouzapw-awesome-omni-skill-solid-router-preloading && rm -rf "$T"
manifest: skills/frontend/solid-router-preloading/SKILL.md
source content

Solid Router Preloading

Complete guide to preloading routes and components in Solid Router. Optimize navigation performance by loading code and data before user commits to navigation.

Automatic Preloading

Solid Router automatically preloads routes based on user intent signals.

Intent Detection

User ActionBehavior
HoverWaits ~20ms before preloading
FocusPreloads immediately

How it works:

  • Router listens for hover/focus on
    <A>
    components
  • Debounces hover for 20ms to ignore accidental passes
  • Loads route module and runs preload function
  • Caches result for instant navigation

Route Preload Function

Export a

preload
function in route modules to seed caches and prepare data.

Basic Preload

// routes/users/[id].tsx
import type { RouteDefinition } from "@solidjs/router";

export const route = {
  preload({ params, location }) {
    // Preload user data
    void getUserQuery(params.id);
    // Preload related data
    void getUserPostsQuery(params.id);
  },
} satisfies RouteDefinition;

export default function UserProfile() {
  // Data already cached from preload
  const user = createAsync(() => getUserQuery(params.id));
  return <div>{user()?.name}</div>;
}

Preload with Search Params

export const route = {
  preload({ params, location, search }) {
    const filters = search.filters;
    void getProductsQuery({ category: params.category, filters });
  },
} satisfies RouteDefinition;

Preload function receives:

  • params
    : Route parameters
  • location
    : Location object
  • search
    : Search params (if using search API)

usePreloadRoute Hook

Imperatively preload routes for custom interactions.

Basic Usage

import { usePreloadRoute } from "@solidjs/router";

function ProductCard({ productId }) {
  const preload = usePreloadRoute();

  const handleMouseEnter = () => {
    // Preload product detail route
    preload(`/products/${productId}`);
  };

  return (
    <div onMouseEnter={handleMouseEnter}>
      Product Card
    </div>
  );
}

With Delay

function ProductCard({ productId }) {
  const preload = usePreloadRoute();

  const handleMouseEnter = () => {
    // Custom delay before preloading
    setTimeout(() => {
      preload(`/products/${productId}`);
    }, 100);
  };

  return <div onMouseEnter={handleMouseEnter}>Product Card</div>;
}

Lazy Component Preloading

Preload nested lazy components that aren't part of route hierarchy.

Lazy Component with Preload

import { lazy } from "solid-js";

const HeavyComponent = lazy(() => import("./HeavyComponent"));

// Preload component
HeavyComponent.preload();

// Later, render it
return <HeavyComponent />;

Coordinating Route and Component Preload

// Route preload
export const route = {
  preload({ params }) {
    // Preload route data
    void getUserQuery(params.id);
    
    // Preload nested lazy component
    UserDetails.preload();
  },
} satisfies RouteDefinition;

const UserDetails = lazy(() => import("./UserDetails"));

export default function UserProfile() {
  return (
    <Suspense>
      <UserDetails />
    </Suspense>
  );
}

Performance Optimization

When to Preload

Good candidates:

  • High-intent interactions (hover, focus)
  • Likely next routes
  • Critical data for navigation

Avoid preloading:

  • Low-probability routes
  • Very large bundles
  • Expensive operations

Measuring Impact

Use profiling tools to measure:

  • Reduced long tasks
  • Faster navigation
  • Network usage trade-offs

Custom Preload Strategy

function SmartPreload({ route, delay = 20 }) {
  const preload = usePreloadRoute();
  let timeout: number;

  const handleIntent = () => {
    timeout = setTimeout(() => {
      preload(route);
    }, delay);
  };

  const cancelPreload = () => {
    clearTimeout(timeout);
  };

  return (
    <div
      onMouseEnter={handleIntent}
      onMouseLeave={cancelPreload}
    >
      <A href={route}>Link</A>
    </div>
  );
}

Common Patterns

Preload on Hover

function NavigationLink({ href, children }) {
  const preload = usePreloadRoute();

  return (
    <A
      href={href}
      onMouseEnter={() => preload(href)}
    >
      {children}
    </A>
  );
}

Preload with Query

export const route = {
  preload({ params }) {
    // Preload multiple queries
    void Promise.all([
      getUserQuery(params.id),
      getUserPostsQuery(params.id),
      getUserFollowersQuery(params.id),
    ]);
  },
} satisfies RouteDefinition;

Conditional Preload

export const route = {
  preload({ params, location }) {
    // Only preload if authenticated
    if (isAuthenticated()) {
      void getUserQuery(params.id);
    }
  },
} satisfies RouteDefinition;

SSR Considerations

Important: Preload functions run during SSR initial render and resume on client hydration.

Best practices:

  • Keep preload functions pure
  • Avoid side effects
  • Use for data fetching only
  • Don't mutate global state
// ✅ Good - pure function
export const route = {
  preload({ params }) {
    void getUserQuery(params.id); // Just fetch data
  },
} satisfies RouteDefinition;

// ❌ Bad - side effects
export const route = {
  preload({ params }) {
    setGlobalState(params.id); // Mutates global state
    void getUserQuery(params.id);
  },
} satisfies RouteDefinition;

Best Practices

  1. Use route preload for data:

    • Seed query caches
    • Prepare route data
    • Warm computations
  2. Use usePreloadRoute for custom:

    • Custom interactions
    • Timers
    • Observer-driven experiences
  3. Preload lazy components separately:

    • Not automatically preloaded
    • Call
      .preload()
      manually
    • Coordinate with route preload
  4. Measure performance:

    • Profile real user flows
    • Avoid over-preloading
    • Balance network cost
  5. Keep preload functions pure:

    • No side effects
    • SSR-safe
    • Idempotent

Summary

  • Automatic: Hover (20ms delay) and focus trigger preload
  • Route preload: Export preload function in route
  • usePreloadRoute: Imperative preloading hook
  • Lazy components: Call
    .preload()
    method
  • SSR: Keep preload functions pure
  • Performance: Measure and optimize