Repository: TanStack/router
Pull request #2477 (2024-10-05 13:45:04)

feat: add default setting for `ssr` in router

nx-cloud[bot]: # ☁️ Nx Cloud Report

CI is running for commit c359a91b195f45390cb7fea77d6fdeefd313ee89.

[📂 Click to track the progress, see the status, the terminal output, and the build insights.](https://cloud.nx.app/cipes/670143029fb2c5408173d0ce?utm_source=pull-request&utm_medium=comment)


---

Sent with 💌 from [NxCloud.](https://nx.app?utm_source=pull-request&utm_medium=comment)
pkg-pr-new[bot]: 
[Open in Stackblitz](https://pkg.pr.new/template/e6895c60-c130-49e0-a552-845220575753)
<details><summary><b>More templates</b></summary><p>

- [tanstack-router-react-example-authenticated-routes](https://pkg.pr.new/template/d2c8cdf5-521d-45b9-a714-31c5c99be38c)
- [tanstack-router-react-example-basic](https://pkg.pr.new/template/441d9a46-ee6b-4d50-8980-eb41fcaf73da)
- [tanstack-router-react-example-basic-default-search-params](https://pkg.pr.new/template/a4b006bd-0cd6-48c8-9aa9-69f21db444c7)
- [tanstack-router-react-example-basic-file-based](https://pkg.pr.new/template/dc0da839-7f98-4c4e-ac36-76f0e4850b5e)
- [tanstack-router-react-example-basic-file-based-codesplitting](https://pkg.pr.new/template/d792c4df-f23c-4231-84e6-93641605db8c)
- [tanstack-router-react-example-react-query](https://pkg.pr.new/template/39e4abf8-c3b8-47f4-b334-5c135f9912b4)
- [tanstack-router-react-example-basic-react-query-file-based](https://pkg.pr.new/template/c3a53b52-6fc1-40aa-b275-332b7f07e4c9)
- [tanstack-router-react-example-basic-ssr-file-based](https://pkg.pr.new/template/35422c8f-10fc-4af8-a726-782382e8a2f2)
- [tanstack-router-react-example-basic-ssr-streaming-file-based](https://pkg.pr.new/template/a213ebbf-69f9-4052-a8ac-5d868d27d7ee)
- [tanstack-router-react-example-basic-virtual-file-based](https://pkg.pr.new/template/32a71e5b-7895-4267-a39e-5e83b832707c)
- [tanstack-router-react-example-basic-virtual-inside-file-based](https://pkg.pr.new/template/c21e722f-2efd-4886-8e9a-257a7bd4ccfb)
- [tanstack-router-react-example-deferred-data](https://pkg.pr.new/template/06005f7c-3896-4a8a-9c89-640e0742b79c)
- [tanstack-router-react-example-kitchen-sink](https://pkg.pr.new/template/0c6decf7-f918-4fcc-9ba7-4a52630ff6ab)
- [tanstack-router-react-example-kitchen-sink-file-based](https://pkg.pr.new/template/cd03fb5c-2c62-42da-93db-776fdb0b268b)
- [tanstack-router-react-example-kitchen-sink-react-query](https://pkg.pr.new/template/abe33806-e2d5-4547-af9e-3850c8d488fe)
- [tanstack-router-react-example-kitchen-sink-react-query-file-based](https://pkg.pr.new/template/ce600981-3df7-4136-aed5-c73e513a755e)
- [tanstack-router-react-example-large-file-based](https://pkg.pr.new/template/974d4820-0fd3-48dc-a072-525c270c876b)
- [tanstack-router-react-example-location-masking](https://pkg.pr.new/template/d28e79ba-6393-42c1-9af7-791eb28c016b)
- [tanstack-router-react-example-navigation-blocking](https://pkg.pr.new/template/78fcab54-78b6-45ea-abda-715124ca3d20)
- [tanstack-router-react-example-quickstart-file-based](https://pkg.pr.new/template/a3460b2d-aba0-4c76-b540-ab3e8d334ff9)
- [tanstack-router-react-example-quickstart](https://pkg.pr.new/template/2c5efbcc-fb39-4047-a835-1da0e095bd8e)
- [tanstack-router-react-example-quickstart-rspack-file-based](https://pkg.pr.new/template/2db28ae5-91d4-4311-9fdd-d88b899688f4)
- [tanstack-router-react-example-scroll-restoration](https://pkg.pr.new/template/934d3040-9204-4428-ac54-293360b576f9)
- [tanstack-router-react-example-quickstart-webpack-file-based](https://pkg.pr.new/template/2ae8897e-d53a-4a5c-9965-7c6416c3d9ec)
- [tanstack-router-search-validator-adapters](https://pkg.pr.new/template/d3b50429-af68-4505-b7da-d1d722bfeb5e)
- [tanstack-start-example-basic](https://pkg.pr.new/template/2de5d76b-1036-4745-aa2c-d4650a3849ee)
- [tanstack-start-example-basic-auth](https://pkg.pr.new/template/984c577d-47fe-4f69-9d84-ff7b38f3255c)
- [tanstack-start-example-basic-react-query](https://pkg.pr.new/template/0fb96660-ebfb-4bfa-842b-98758fdd62d4)
- [tanstack-start-example-clerk-basic](https://pkg.pr.new/template/0959337a-d589-4e76-9496-959514fe4054)
- [tanstack-start-example-basic-rsc](https://pkg.pr.new/template/8ba6c34e-3e99-4e4a-a63c-7ba0473a2fea)
- [tanstack-start-example-convex-trellaux](https://pkg.pr.new/template/6c3650f9-f756-4a26-9bfb-3fc8372a063f)
- [tanstack-start-example-counter](https://pkg.pr.new/template/fdfdf0ef-4c51-46e5-92bc-8c268454f580)
- [tanstack-start-example-supabase-basic](https://pkg.pr.new/template/5e7867b9-ba6d-4080-ba2b-0d9e40938050)
- [tanstack-start-example-trellaux](https://pkg.pr.new/template/beef573b-97d6-4b88-9da7-09ecb8e20294)
- [tanstack-router-react-example-with-framer-motion](https://pkg.pr.new/template/8af968ea-449b-4636-9d15-7662f48d3440)
- [tanstack-router-react-example-with-trpc](https://pkg.pr.new/template/8e3cd5a8-a575-4ee1-8cd6-3cf3e6de849a)
- [tanstack-router-react-example-with-trpc-react-query](https://pkg.pr.new/template/92fe95bc-f550-461b-bc88-a1c6ff46f645)

</p></details>
      
    


<details><summary><b>@tanstack/create-router</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/create-router@2477
```

</p></details>
      
    

<details><summary><b>@tanstack/eslint-plugin-router</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/eslint-plugin-router@2477
```

</p></details>
      
    

<details><summary><b>@tanstack/react-cross-context</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/react-cross-context@2477
```

</p></details>
      
    

<details><summary><b>@tanstack/history</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/history@2477
```

</p></details>
      
    

<details><summary><b>@tanstack/react-router</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/react-router@2477
```

</p></details>
      
    

<details><summary><b>@tanstack/router-arktype-adapter</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/router-arktype-adapter@2477
```

</p></details>
      
    

<details><summary><b>@tanstack/react-router-with-query</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/react-router-with-query@2477
```

</p></details>
      
    

<details><summary><b>@tanstack/router-cli</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/router-cli@2477
```

</p></details>
      
    

<details><summary><b>@tanstack/router-generator</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/router-generator@2477
```

</p></details>
      
    

<details><summary><b>@tanstack/router-devtools</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/router-devtools@2477
```

</p></details>
      
    

<details><summary><b>@tanstack/router-plugin</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/router-plugin@2477
```

</p></details>
      
    

<details><summary><b>@tanstack/router-valibot-adapter</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/router-valibot-adapter@2477
```

</p></details>
      
    

<details><summary><b>@tanstack/router-vite-plugin</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/router-vite-plugin@2477
```

</p></details>
      
    

<details><summary><b>@tanstack/router-zod-adapter</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/router-zod-adapter@2477
```

</p></details>
      
    

<details><summary><b>@tanstack/start</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/start@2477
```

</p></details>
      
    

<details><summary><b>@tanstack/start-vite-plugin</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/start-vite-plugin@2477
```

</p></details>
      
    

<details><summary><b>@tanstack/virtual-file-routes</b></summary><p>

```
pnpm add https://pkg.pr.new/@tanstack/virtual-file-routes@2477
```

</p></details>
      
    

_commit: <a href="https://github.com/TanStack/router/runs/31119373121"><code>c359a91</code></a>_


Patch:
diff --git a/packages/react-router/src/route.ts b/packages/react-router/src/route.ts
index 1b211228a..6dd59a8a4 100644
--- a/packages/react-router/src/route.ts
+++ b/packages/react-router/src/route.ts
@@ -882,6 +882,7 @@ export class Route<
   private _path!: TPath
   private _fullPath!: TFullPath
   private _to!: TrimPathRight<TFullPath>
+  private _ssr!: boolean
 
   public get to() {
     /* invariant(
@@ -916,6 +917,10 @@ export class Route<
     return this._fullPath
   }
 
+  public get ssr() {
+    return this._ssr
+  }
+
   // Optional
   children?: TChildren
   originalIndex?: number
@@ -984,7 +989,7 @@ export class Route<
     loaderDeps: TLoaderDeps
   }
 
-  init = (opts: { originalIndex: number }): void => {
+  init = (opts: { originalIndex: number; defaultSsr?: boolean }): void => {
     this.originalIndex = opts.originalIndex
 
     const options = this.options as
@@ -1051,6 +1056,7 @@ export class Route<
     // this.customId = customId as TCustomId
     this._fullPath = fullPath as TFullPath
     this._to = fullPath as TrimPathRight<TFullPath>
+    this._ssr = options?.ssr ?? opts.defaultSsr ?? true
   }
 
   addChildren<
diff --git a/packages/react-router/src/router.ts b/packages/react-router/src/router.ts
index 2a9e9a3af..e4e3e7907 100644
--- a/packages/react-router/src/router.ts
+++ b/packages/react-router/src/router.ts
@@ -451,6 +451,8 @@ export interface RouterOptions<
    * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RouterOptionsType#isserver property)
    */
   isServer?: boolean
+
+  defaultSsr?: boolean
 }
 
 export interface RouterErrorSerializer<TSerializedError> {
@@ -773,13 +775,19 @@ export class Router<
 
     const notFoundRoute = this.options.notFoundRoute
     if (notFoundRoute) {
-      notFoundRoute.init({ originalIndex: 99999999999 })
+      notFoundRoute.init({
+        originalIndex: 99999999999,
+        defaultSsr: this.options.defaultSsr,
+      })
       ;(this.routesById as any)[notFoundRoute.id] = notFoundRoute
     }
 
     const recurseRoutes = (childRoutes: Array<AnyRoute>) => {
       childRoutes.forEach((childRoute, i) => {
-        childRoute.init({ originalIndex: i })
+        childRoute.init({
+          originalIndex: i,
+          defaultSsr: this.options.defaultSsr,
+        })
 
         const existingRoute = (this.routesById as any)[childRoute.id]
 
diff --git a/packages/router-plugin/package.json b/packages/router-plugin/package.json
index c01befc73..eb95dcd68 100644
--- a/packages/router-plugin/package.json
+++ b/packages/router-plugin/package.json
@@ -25,6 +25,7 @@
   ],
   "scripts": {
     "clean": "rimraf ./dist && rimraf ./coverage",
+    "clean:snapshots": "rimraf **/*snapshot* --glob",
     "test": "pnpm test:eslint && pnpm test:types && pnpm test:build && pnpm test:unit",
     "test:unit": "vitest",
     "test:unit:dev": "vitest --watch",
diff --git a/packages/router-plugin/src/core/code-splitter/compilers.ts b/packages/router-plugin/src/core/code-splitter/compilers.ts
index 53a07fa9b..96ed3d821 100644
--- a/packages/router-plugin/src/core/code-splitter/compilers.ts
+++ b/packages/router-plugin/src/core/code-splitter/compilers.ts
@@ -148,7 +148,7 @@ export function compileCodeSplitReferenceRoute(opts: ParseAstOptions) {
                             }
 
                             prop.value = template.expression(
-                              `lazyRouteComponent($$splitComponentImporter, 'component', () => Route.options.ssr)`,
+                              `lazyRouteComponent($$splitComponentImporter, 'component', () => Route.ssr)`,
                             )()
 
                             programPath.pushContainer('body', [


Test patch:
diff --git a/packages/router-plugin/tests/code-splitter/snapshots/destructured-react-memo-imported-component.tsx b/packages/router-plugin/tests/code-splitter/snapshots/destructured-react-memo-imported-component.tsx
index 632272053..44ed2c32f 100644
--- a/packages/router-plugin/tests/code-splitter/snapshots/destructured-react-memo-imported-component.tsx
+++ b/packages/router-plugin/tests/code-splitter/snapshots/destructured-react-memo-imported-component.tsx
@@ -4,6 +4,6 @@ const $$splitComponentImporter = () => import('tsr-split:destructured-react-memo
 import { lazyRouteComponent } from '@tanstack/react-router';
 import { createFileRoute } from '@tanstack/react-router';
 export const Route = createFileRoute('/')({
-  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.options.ssr),
+  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.ssr),
   loader: lazyFn($$splitLoaderImporter, 'loader')
 });
\ No newline at end of file
diff --git a/packages/router-plugin/tests/code-splitter/snapshots/function-declaration.tsx b/packages/router-plugin/tests/code-splitter/snapshots/function-declaration.tsx
index 553023513..bad40895f 100644
--- a/packages/router-plugin/tests/code-splitter/snapshots/function-declaration.tsx
+++ b/packages/router-plugin/tests/code-splitter/snapshots/function-declaration.tsx
@@ -5,5 +5,5 @@ import { lazyFn } from '@tanstack/react-router';
 import { createFileRoute } from '@tanstack/react-router';
 export const Route = createFileRoute('/posts')({
   loader: lazyFn($$splitLoaderImporter, 'loader'),
-  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.options.ssr)
+  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.ssr)
 });
\ No newline at end of file
diff --git a/packages/router-plugin/tests/code-splitter/snapshots/imported-default-component-destructured-loader.tsx b/packages/router-plugin/tests/code-splitter/snapshots/imported-default-component-destructured-loader.tsx
index c815e5eae..57b8ab4e0 100644
--- a/packages/router-plugin/tests/code-splitter/snapshots/imported-default-component-destructured-loader.tsx
+++ b/packages/router-plugin/tests/code-splitter/snapshots/imported-default-component-destructured-loader.tsx
@@ -4,6 +4,6 @@ const $$splitComponentImporter = () => import('tsr-split:imported-default-compon
 import { lazyRouteComponent } from '@tanstack/react-router';
 import { createFileRoute } from '@tanstack/react-router';
 export const Route = createFileRoute('/')({
-  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.options.ssr),
+  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.ssr),
   loader: lazyFn($$splitLoaderImporter, 'loader')
 });
\ No newline at end of file
diff --git a/packages/router-plugin/tests/code-splitter/snapshots/imported-default-component.tsx b/packages/router-plugin/tests/code-splitter/snapshots/imported-default-component.tsx
index 9334a71cf..f37448ed3 100644
--- a/packages/router-plugin/tests/code-splitter/snapshots/imported-default-component.tsx
+++ b/packages/router-plugin/tests/code-splitter/snapshots/imported-default-component.tsx
@@ -2,5 +2,5 @@ const $$splitComponentImporter = () => import('tsr-split:imported-default-compon
 import { lazyRouteComponent } from '@tanstack/react-router';
 import { createFileRoute } from '@tanstack/react-router';
 export const Route = createFileRoute('/')({
-  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.options.ssr)
+  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.ssr)
 });
\ No newline at end of file
diff --git a/packages/router-plugin/tests/code-splitter/snapshots/imported.tsx b/packages/router-plugin/tests/code-splitter/snapshots/imported.tsx
index fe182f9de..693dac974 100644
--- a/packages/router-plugin/tests/code-splitter/snapshots/imported.tsx
+++ b/packages/router-plugin/tests/code-splitter/snapshots/imported.tsx
@@ -4,6 +4,6 @@ const $$splitComponentImporter = () => import('tsr-split:imported.tsx?tsr-split'
 import { lazyRouteComponent } from '@tanstack/react-router';
 import { createFileRoute } from '@tanstack/react-router';
 export const Route = createFileRoute('/')({
-  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.options.ssr),
+  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.ssr),
   loader: lazyFn($$splitLoaderImporter, 'loader')
 });
\ No newline at end of file
diff --git a/packages/router-plugin/tests/code-splitter/snapshots/inline.tsx b/packages/router-plugin/tests/code-splitter/snapshots/inline.tsx
index 2387da804..0ff78ef67 100644
--- a/packages/router-plugin/tests/code-splitter/snapshots/inline.tsx
+++ b/packages/router-plugin/tests/code-splitter/snapshots/inline.tsx
@@ -2,7 +2,7 @@ const $$splitComponentImporter = () => import('tsr-split:inline.tsx?tsr-split');
 import { lazyRouteComponent } from '@tanstack/react-router';
 import { createFileRoute } from '@tanstack/react-router';
 export const Route = createFileRoute('/')({
-  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.options.ssr)
+  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.ssr)
 });
 Route.addChildren([]);
 export const test = 'test';
\ No newline at end of file
diff --git a/packages/router-plugin/tests/code-splitter/snapshots/random-number.tsx b/packages/router-plugin/tests/code-splitter/snapshots/random-number.tsx
index 80d8f1e91..dbe8c7d6f 100644
--- a/packages/router-plugin/tests/code-splitter/snapshots/random-number.tsx
+++ b/packages/router-plugin/tests/code-splitter/snapshots/random-number.tsx
@@ -7,5 +7,5 @@ export const textColors = [`text-rose-500`, `text-yellow-500`, `text-teal-500`,
 export const gradients = [`from-rose-500 to-yellow-500`, `from-yellow-500 to-teal-500`, `from-teal-500 to-violet-500`, `from-blue-500 to-pink-500`];
 export const Route = createFileRoute('/')({
   loader: lazyFn($$splitLoaderImporter, 'loader'),
-  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.options.ssr)
+  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.ssr)
 });
\ No newline at end of file
diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react-memo-component.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react-memo-component.tsx
index 319637253..58a289239 100644
--- a/packages/router-plugin/tests/code-splitter/snapshots/react-memo-component.tsx
+++ b/packages/router-plugin/tests/code-splitter/snapshots/react-memo-component.tsx
@@ -4,6 +4,6 @@ const $$splitComponentImporter = () => import('tsr-split:react-memo-component.ts
 import { lazyRouteComponent } from '@tanstack/react-router';
 import { createFileRoute } from '@tanstack/react-router';
 export const Route = createFileRoute('/')({
-  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.options.ssr),
+  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.ssr),
   loader: lazyFn($$splitLoaderImporter, 'loader')
 });
\ No newline at end of file
diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react-memo-imported-component.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react-memo-imported-component.tsx
index 891cf7dc4..6ac9b1df7 100644
--- a/packages/router-plugin/tests/code-splitter/snapshots/react-memo-imported-component.tsx
+++ b/packages/router-plugin/tests/code-splitter/snapshots/react-memo-imported-component.tsx
@@ -4,6 +4,6 @@ const $$splitComponentImporter = () => import('tsr-split:react-memo-imported-com
 import { lazyRouteComponent } from '@tanstack/react-router';
 import { createFileRoute } from '@tanstack/react-router';
 export const Route = createFileRoute('/')({
-  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.options.ssr),
+  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.ssr),
   loader: lazyFn($$splitLoaderImporter, 'loader')
 });
\ No newline at end of file
diff --git a/packages/router-plugin/tests/code-splitter/snapshots/retain-exports-loader.tsx b/packages/router-plugin/tests/code-splitter/snapshots/retain-exports-loader.tsx
index e95bfc461..fda27416a 100644
--- a/packages/router-plugin/tests/code-splitter/snapshots/retain-exports-loader.tsx
+++ b/packages/router-plugin/tests/code-splitter/snapshots/retain-exports-loader.tsx
@@ -7,7 +7,7 @@ export function loaderFn() {
   };
 }
 export const Route = createFileRoute('/_layout')({
-  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.options.ssr),
+  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.ssr),
   loader: loaderFn
 });
 export const SIDEBAR_WIDTH = '150px';
diff --git a/packages/router-plugin/tests/code-splitter/snapshots/useStateDestructure.tsx b/packages/router-plugin/tests/code-splitter/snapshots/useStateDestructure.tsx
index 7a3f55720..7229cc62f 100644
--- a/packages/router-plugin/tests/code-splitter/snapshots/useStateDestructure.tsx
+++ b/packages/router-plugin/tests/code-splitter/snapshots/useStateDestructure.tsx
@@ -4,7 +4,7 @@ import { startProject } from '~/projects/start';
 import { createFileRoute } from '@tanstack/react-router';
 import { seo } from '~/utils/seo';
 export const Route = createFileRoute('/_libraries/start/$version/')({
-  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.options.ssr),
+  component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.ssr),
   meta: () => seo({
     title: startProject.name,
     description: startProject.description