You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
|`transform`|`string \| (asset) => string \| Promise<string>`| A string prefix or callback, same as the shorthand forms above.|
116
116
|`createTransform`|`(ctx: { warmup: true } \| { warmup: false; request: Request }) => (asset) => string \| Promise<string>`| Async factory that runs once per manifest computation and returns a per-asset transform. Mutually exclusive with `transform`. |
117
-
|`cache`|`boolean`| Whether to cache the transformed manifest. Defaults to `true`. |
118
-
|`warmup`|`boolean`| When `true`, warms up the cached manifest on server startup (prod only). Defaults to `false`. |
117
+
|`cache`|`boolean`| Whether to cache the transformed manifest. Defaults to `true`.|
118
+
|`warmup`|`boolean`| When `true`, warms up the cached manifest on server startup (prod only). Defaults to `false`.|
119
119
120
120
If you need to do async work once per manifest computation (e.g. fetch a CDN origin from a service) and then transform many URLs, prefer `createTransform`:
121
121
@@ -165,6 +165,33 @@ This has no effect in development mode, or when `cache: false`.
165
165
166
166
> **Note:** In development mode (`TSS_DEV_SERVER`), caching is always skipped regardless of the `cache` setting, so you always get fresh manifests.
167
167
168
+
## Recommended: Set `base: ''` for Client-Side Navigation
169
+
170
+
`transformAssetUrls` rewrites the URLs in the SSR HTML — modulepreload hints, stylesheets, and the client entry script. This means the browser's initial page load fetches all assets from the CDN.
171
+
172
+
However, when users navigate client-side (e.g., clicking a `<Link>`), TanStack Router lazy-loads route chunks using `import()` calls with paths that were baked in at **build time** by Vite. By default, Vite uses `base: '/'`, which produces absolute paths like `/assets/about-abc123.js`. These resolve against the **app server's origin**, not the CDN — even though the entry module was loaded from the CDN.
173
+
174
+
To fix this, set `base: ''` in your Vite config:
175
+
176
+
```ts
177
+
// vite.config.ts
178
+
exportdefaultdefineConfig({
179
+
base: '',
180
+
// ... plugins, etc.
181
+
})
182
+
```
183
+
184
+
With `base: ''`, Vite generates **relative** import paths for client-side chunks. Since the client entry module was loaded from the CDN (thanks to `transformAssetUrls`), all relative `import()` calls resolve against the CDN origin. This ensures that lazy-loaded route chunks during client-side navigation are also served from the CDN.
185
+
186
+
Using an empty string rather than `'./'` is important — both produce relative client-side imports, but `base: ''` preserves the correct root-relative paths (`/assets/...`) in the SSR manifest so that `transformAssetUrls` can properly prepend the CDN origin.
> **Tip:**`base: ''` is recommended whenever you use `transformAssetUrls` so that all assets — both on initial load and during client-side navigation — are consistently served from the CDN.
194
+
168
195
## What This Does NOT Cover
169
196
170
197
`transformAssetUrls` only rewrites URLs in the TanStack Start manifest — the tags emitted during SSR for preloading and bootstrapping the application.
0 commit comments