Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
4a50173
add notes about route and component preloading
atilafassina Oct 18, 2025
50d0a0c
fix backtick typo
atilafassina Oct 18, 2025
a2ab463
fix bad URL
atilafassina Oct 18, 2025
f364e32
"start" fetching data
atilafassina Oct 18, 2025
a4c79c1
both `<A>` and `<a>` have the preload behavior, remove ambiguous sent…
atilafassina Oct 18, 2025
7937b09
more content on lazy loading and nested components
atilafassina Oct 19, 2025
0fe3593
Merge branch 'main' into preload-entries
kodiakhq[bot] Oct 20, 2025
e640128
fix typo
atilafassina Oct 20, 2025
a46fd80
Merge branch 'main' into preload-entries
kodiakhq[bot] Oct 20, 2025
f805d73
Merge branch 'main' into preload-entries
kodiakhq[bot] Oct 20, 2025
5788b7d
Merge branch 'main' into preload-entries
kodiakhq[bot] Oct 20, 2025
3d47fe4
Merge branch 'main' into preload-entries
kodiakhq[bot] Oct 21, 2025
203df8d
Merge branch 'main' into preload-entries
kodiakhq[bot] Oct 21, 2025
b1a0fb0
clarify sentence with manually preloading
atilafassina Oct 23, 2025
4b4f2e3
better English :)
atilafassina Oct 23, 2025
143ba25
typo :)
atilafassina Oct 23, 2025
738edde
Merge branch 'main' into preload-entries
kodiakhq[bot] Oct 26, 2025
4be0415
Update src/routes/solid-router/advanced-concepts/preloading.mdx
atilafassina Oct 26, 2025
f5fdd71
Merge branch 'main' into preload-entries
kodiakhq[bot] Oct 27, 2025
c186d75
Merge branch 'main' into preload-entries
kodiakhq[bot] Oct 27, 2025
0ec7ff5
Merge branch 'main' into preload-entries
kodiakhq[bot] Oct 28, 2025
48469c4
Merge branch 'main' into preload-entries
kodiakhq[bot] Oct 28, 2025
d29d5fe
Merge branch 'main' into preload-entries
kodiakhq[bot] Oct 28, 2025
e969cad
Merge branch 'main' into preload-entries
kodiakhq[bot] Oct 28, 2025
7eec91d
Merge branch 'main' into preload-entries
kodiakhq[bot] Oct 28, 2025
f291d4d
Merge branch 'main' into preload-entries
kodiakhq[bot] Oct 31, 2025
8057066
Merge branch 'main' into preload-entries
kodiakhq[bot] Nov 4, 2025
5410b66
Merge branch 'main' into preload-entries
kodiakhq[bot] Nov 4, 2025
488749c
Merge branch 'main' into preload-entries
kodiakhq[bot] Nov 8, 2025
1406b87
Merge branch 'main' into preload-entries
kodiakhq[bot] Nov 9, 2025
b4dcd8f
Merge branch 'main' into preload-entries
kodiakhq[bot] Nov 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/routes/guides/routing-and-navigation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -461,8 +461,7 @@ The preload function is then passed in the `<Route>` definition:
You can export preload functions and data wrappers that correspond to routes from a dedicated `[route].data.js` or `[route].data.ts` file.
This pattern provides a way to import the data function without loading anything else.

```jsx
// src/pages/users/[id].data.js
```tsx title="src/pages/users/[id].data.js"
import { query } from "@solidjs/router";

export const getUser = query(async (id) => {
Expand Down Expand Up @@ -509,8 +508,7 @@ render(
`[id].jsx` contains the component that gets rendered.
When you wrap the function within [`createAsync`](/solid-router/reference/data-apis/create-async) with the imported function, it will yield [a signal](/concepts/signals) once the anticipated promise resolves.

```jsx
// [id].jsx
```tsx title="[id].tsx"
import { createAsync } from "@solidjs/router";
import { getUser } from "./[id].data";

Expand Down
73 changes: 62 additions & 11 deletions src/routes/reference/component-apis/lazy.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,75 @@ description: >-
performance. Components load on-demand and integrate with Suspense.
---

```ts
Used to lazy load components to allow for code splitting.
Components are not loaded until rendered or manually preloaded.

```tsx title="app.tsx"
import { lazy } from "solid-js"

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

function App(props: { title: string }) {
return (
<ComponentA title={props.title} />
)
}
```

Lazy loaded components can be used the same as its statically imported counterpart, receiving props etc.
Lazy components trigger `<Suspense>`

## Preloading data in Nested Lazy Components

Top-level lazy components will automatically be preloaded as well as their preload functions.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there's a concept of "top level lazy components". The only lazy components that are preloaded are route components, which means this section belongs in the router docs.

It's definitely worth calling out that lazy route components are preloaded automatically, but that callout should be further down in this page, and should link to the router docs where its explained in more detail.

However, nested lazy components will not be preloaded automatically because they are not part of the route hierarchy.
To preload such components, you can use the `preload` method exposed on the lazy component.

```tsx title="component-with-preload.tsx"
import { lazy } from "solid-js"
import type { Component } from "solid-js"

const Nested = lazy(() => import("./Nested"))

const ComponentWithPreload: Component = () => {
// preload Nested component when needed
async function handlePreload() {
await Nested.preload()
}

return (
<div>
<button onClick={handlePreload}>Preload Nested Component</button>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the time the button is visible and before it's able to be clicked, <Nested /> is loaded and rendered already no?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, it should look something like this

const ComponentWithPreload = () => {
  const [showNested, setShowNested] = createSignal(false)

  return (
	<div>
	  <button
        onMouseEnter={() => Nested.preload()}
        onClick={() => setShowNested(true)}
      >Preload Nested Component</button>
      <Show when={showNested()}>
	    <Nested />
      </Show>
	</div>
  )
}

<Nested />
</div>
)
}

```

## Type Signature

```tsx
function lazy<T extends Component<any>>(
fn: () => Promise<{ default: T }>
): T & { preload: () => Promise<T> }
```

Used to lazy load components to allow for code splitting.
Components are not loaded until rendered.
Lazy loaded components can be used the same as its statically imported counterpart, receiving props etc.
Lazy components trigger `<Suspense>`
### Type Parameters

```tsx
// wrap import
const ComponentA = lazy(() => import("./ComponentA"));
| Name | Constraint | Description |
| ---- | ---------- | ----------- |
| `T` | `Component<any>` | The component type that will be lazily loaded (including its props).

### Parameters

| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `fn` | `() => Promise<{ default: T }>` | Yes | A function that returns a dynamic import resolving to the component as the `default` export. |

### Returns

| Type | Description |
| ---- | ----------- |
| `T & { preload: () => Promise<T> }` | A renderable component compatible with `T` that also exposes a `preload()` method to eagerly load the module. |

// use in JSX
<ComponentA title={props.title} />
```
2 changes: 1 addition & 1 deletion src/routes/solid-router/advanced-concepts/data.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"title": "Advanced concepts",
"pages": ["lazy-loading.mdx"]
"pages": ["preloading.mdx", "lazy-loading.mdx"]
}
24 changes: 24 additions & 0 deletions src/routes/solid-router/advanced-concepts/preloading.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
title: Preloading
---

Anchors in Solid Router will preload routes by default on link hover/focus to improve perceived performance.

To enhance preloading, you can define the `preload` function on your route definition.
When on a [SolidStart](/solid-start) application, this function can also run on the server during the initial page load to start fetching data before rendering. When in a Single-Page Application (SPA), it will load the route's component and its `preload` function when the user hovers or focuses on a link.

| user action | route behavior |
| ----------- | -------------------------------------- |
| hover | with a 300ms delay to avoid excessive preloading |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious where you got the 300ms from. I can only see a 20ms timeout here

| focus | immediately |
Comment on lines +8 to +13
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the SolidStart section might be more appropriate in the reference section as a callout so it doesn't get buried here.

Following that change, I also believe it might be better to show a basic code snippet of what the hover would look like. Doesn't have to be too complex, just enough to get the idea across for how it should look.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the code snippet is in the respective API references. This entry is to explain conceptually how preloading works in Solid Router. I added links to the the APIs so things didn't get too repetitive

Not sure what you mean about the hover snippet, that's just the browser API, there's no code from the user to manage or handle that. If they hover or focus the anchor tag, preloading will happen.

Remember: preloading is default behavior. Altering it is an advanced concept for users, most cases we want people to feel it "just works".

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think as it stands for me it feels more like an extension of the ref page vs an exposure to the concept as a whole. What I meant by the hover example was that it might make it feel less like a ref page if there is some form of an example on the page of what it'd look like to modify it.

My explanation wasn't entirely great (I'm sorry about that) but I'll try to give you a bit more of an idea as to what I mean tomorrow (unless @devagrawal09 has any ideas before then).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if there is some form of an example on the page of what it'd look like to modify it.
There's no way to modify the preload threshold. This is a magical number to prevent eager preloading.

The hover in this case is the regular browser hover, there's nothing framework specific on this. Regular mouse hovering a link will fire a 300ms timeout that will preload data once fulfilled.

Extending on this right here feels to me like documenting browser APIs or framework implementation details.
The reason I added this table here is only to be more transparent about how the framework works under the hood.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @LadyBluenotes that a more detailed explanation of what happens during SSR belongs in the solid-start docs, but it's definitely worth a callout on this page that during SSR the preload function will run before rendering, so that data fetching can be kicked off earlier.
SolidStart docs already explain this in more detail so we should provide a link here.


## Imperative Preloading

You can also use the [`usePreloadRoute`](/solid-router/reference/primitives/use-preload-route) helper to preload routes programmatically in response to events other than link hover/focus, such as button clicks or timers.
This helper will load only the route's component by default, but it can receive a configuration object to also load the data.

## Preloading and Lazy Loading

When a route has nested lazy components, such components will not be part of the route hierarchy, so they **will not** be preloaded with the route. To preload such components, you can use the `preload()` function returned from calling the [`lazy()`](https://docs.solidjs.com/reference/component-apis/lazy) component API.

To learn more about lazy loading components, see the [`lazy`](/reference/component-apis/lazy#preloading-data-in-nested-lazy-components) documentation.
24 changes: 22 additions & 2 deletions src/routes/solid-router/reference/primitives/use-preload-route.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,30 @@ description: >-
prefetching route data before navigation in your SolidJS app.
---

`usePreloadRoute` returns a function that can be used to preload a route manually. This is what happens automatically with link hovering and similar focus based behavior, but it is available here as an API.
`usePreloadRoute` returns a function that can be used to preload a route manually.

```js
```ts
const preload = usePreloadRoute();

preload(`/users/settings`, { preloadData: true });
```

## Usage

Routes are preloaded by default within Solid Router contexts.
This helper is useful when you want to preload a route in response to some other event, such as a button click or a timer.

## Type Signature

### Parameters

| Parameter | Type | Required | Description |
| --------- | -------- | -------- | ------------------------------------ |
| `to` | `To` | Yes | The route path to preload |
| `options` | `object` | No | Configuration options for preloading |

### Options

| Option | Type | Default | Description |
| ------------- | --------- | ------- | ------------------------------------------------------------------- |
| `preloadData` | `boolean` | `false` | Whether to preload the route's data in addition to the route itself |