diff --git a/docs/router/config.json b/docs/router/config.json index dc89691eb5a..80aeeb9707c 100644 --- a/docs/router/config.json +++ b/docs/router/config.json @@ -46,6 +46,23 @@ "to": "framework/react/decisions-on-dx" } ] + }, + { + "label": "solid", + "children": [ + { + "label": "Overview", + "to": "framework/solid/overview" + }, + { + "label": "Installation", + "to": "framework/solid/installation" + }, + { + "label": "Quick Start", + "to": "framework/solid/quick-start" + } + ] } ] }, @@ -189,6 +206,10 @@ "to": "framework/react/guide/render-optimizations" } ] + }, + { + "label": "solid", + "children": [] } ] }, @@ -204,6 +225,10 @@ "to": "framework/react/api/router" } ] + }, + { + "label": "solid", + "children": [] } ] }, @@ -316,6 +341,10 @@ "to": "framework/react/examples/router-monorepo-react-query" } ] + }, + { + "label": "solid", + "children": [] } ] } diff --git a/docs/router/framework/solid/installation.md b/docs/router/framework/solid/installation.md new file mode 100644 index 00000000000..6b41c85ebbc --- /dev/null +++ b/docs/router/framework/solid/installation.md @@ -0,0 +1,24 @@ +--- +title: Installation +--- + +You can install TanStack Router with any [NPM](https://npmjs.com) package manager. + +```sh +npm install @tanstack/solid-router +# or +pnpm add @tanstack/solid-router +# or +yarn add @tanstack/solid-router +# or +bun add @tanstack/solid-router +# or +deno add npm:@tanstack/solid-router +``` + +### Requirements + +- `solid-js`v1.x.x +- TypeScript >= v5.3.x (TypeScript is optional, but recommended) + - We aim to support the last five minor versions of TypeScript. If you are using an older version, you may run into issues. Please upgrade to the latest version of TypeScript to ensure compatibility. + - We may drop support for older versions of TypeScript, outside of the range mentioned above, without warning in a minor or patch release. diff --git a/docs/router/framework/solid/overview.md b/docs/router/framework/solid/overview.md new file mode 100644 index 00000000000..70c1042fdf5 --- /dev/null +++ b/docs/router/framework/solid/overview.md @@ -0,0 +1,147 @@ +--- +title: Overview +--- + +**TanStack Router is a router for building React and Solid applications**. Some of its features include: + +- 100% inferred TypeScript support +- Typesafe navigation +- Nested Routing and layout routes +- Built-in Route Loaders w/ SWR Caching +- Designed for client-side data caches (TanStack Query, SWR, etc.) +- Automatic route prefetching +- Asynchronous route elements and error boundaries +- File-based Route Generation +- Typesafe JSON-first Search Params state management APIs +- Path and Search Parameter Schema Validation +- Search Param Navigation APIs +- Custom Search Param parser/serializer support +- Search param middleware +- Route matching/loading middleware + +To get started quickly, head to the next page. For a more lengthy explanation, buckle up while I bring you up to speed! + +## "A Fork in the Route" + +Using a router to build applications is widely regarded as a must-have and is usually one of the first choices you’ll make in your tech stack. + +**Does this mean that TanStack Router is a framework?** + +TanStack Router itself is not a "framework" in the traditional sense, since it doesn't address a few other common full-stack concerns. However TanStack Router has been designed to be upgradable to a full-stack framework when used in conjunction with other tools that address bundling, deployments, and server-side-specific functionality. This is why we are currently developing [TanStack Start](https://tanstack.com/start), a full-stack framework that is built on top of TanStack Router and tools like Nitro, and Vite. + +For a deeper dive on the history of TanStack Router, feel free to read [TanStack Router's History](./decisions-on-dx.md#tanstack-routers-origin-story). + +## Why TanStack Router? + +TanStack Router delivers on the same fundamental expectations as other routers that you’ve come to expect: + +- Nested routes, layout routes, grouped routes +- File-based Routing +- Parallel data loading +- Prefetching +- URL Path Params +- Error Boundaries and Handling +- SSR +- Route Masking + +And it also delivers some new features that raise the bar: + +- 100% inferred TypeScript support +- Typesafe navigation +- Built-in SWR Caching for loaders +- Designed for client-side data caches (TanStack Query, SWR, etc.) +- Typesafe JSON-first Search Params state management APIs +- Path and Search Parameter Schema Validation +- Search Parameter Navigation APIs +- Custom Search Param parser/serializer support +- Search param middleware +- Inherited Route Context +- Mixed file-based and code-based routing + +Let’s dive into some of the more important ones in more detail! + +## 100% Inferred TypeScript Support + +Everything these days is written “in Typescript” or at the very least offers type definitions that are veneered over runtime functionality, but too few packages in the ecosystem actually design their APIs with TypeScript in mind. So while I’m pleased that your router is auto-completing your option fields and catching a few property/method typos here and there, there is much more to be had. + +- TanStack Router is fully aware of all of your routes and their configuration at any given point in your code. This includes the path, path params, search params, context, and any other configuration you’ve provided. Ultimately this means that you can navigate to any route in your app with 100% type safety and confidence that your link or navigate call will succeed. +- TanStack Router provides lossless type-inference. It uses countless generic type parameters to enforce and propagate any type information you give it throughout the rest its API and ultimately your app. No other router offers this level of type safety and developer confidence. + +What does all of that mean for you? + +- Faster feature development with auto-completion and type hints +- Safer and faster refactors +- Confidence that your code will work as expected + +## 1st Class Search Parameters + +Search parameters are often an afterthought, treated like a black box of strings (or string) that you can parse and update, but not much else. Existing solutions are **not** type-safe either, adding to the caution that is required to deal with them. Even the most "modern" frameworks and routers and leave it up to you to figure out how to manage this state. Sometimes they'll parse the search string into an object for you, or sometimes you're left to do it yourself with `URLSearchParams`. + +Let's step back and remember that **search params are the most powerful state manager in your entire application.** They are global, serializable, bookmarkable, and shareable making them the perfect place to store any kind of state that needs to survive a page refresh or a social share. + +To live up to that responsibility, search parameters are a first-class citizen in TanStack Router. While still based on standard URLSearchParams, TanStack Router uses a powerful parser/serializer to manage deeper and more complex data structures in your search params, all while keeping them type-safe and easy to work with. + +**It's like having `useState` right in the URL!** + +Search parameters are: + +- Automatically parsed and serialized as JSON +- Validated and typed +- Inherited from parent routes +- Accessible in loaders, components, and hooks +- Easily modified with the useSearch hook, Link, navigate, and router.navigate APIs +- Customizable with a custom search filters and middleware +- Subscribed via fine-grained search param selectors for efficient re-renders + +Once you start using TanStack Router's search parameters, you'll wonder how you ever lived without them. + +## Built-In Caching and Friendly Data Loading + +Data loading is a critical part of any application and while most existing routers offer some form of critical data loading APIs, they often fall short when it comes to caching and data lifecycle management. Existing solutions suffer from a few common problems: + +- No caching at all. Data is always fresh, but your users are left waiting for frequently accessed data to load over and over again. +- Overly-aggressive caching. Data is cached for too long, leading to stale data and a poor user experience. +- Blunt invalidation strategies and APIs. Data may be invalidated too often, leading to unnecessary network requests and wasted resources, or you may not have any fine-grained control over when data is invalidated at all. + +TanStack Router solves these problems with a two-prong approach to caching and data loading: + +### Built-in Cache + +TanStack Router provides a light-weight built-in caching layer that works seamlessly with the Router. This caching layer is loosely based on TanStack Query, but with fewer features and a much smaller API surface area. Like TanStack Query, sane but powerful defaults guarantee that your data is cached for reuse, invalidated when necessary, and garbage collected when not in use. It also provides a simple API for invalidating the cache manually when needed. + +### Flexible & Powerful Data Lifecycle APIs + +TanStack Router is designed with a flexible and powerful data loading API that more easily integrates with existing data fetching libraries like TanStack Query, SWR, Apollo, Relay, or even your own custom data fetching solution. Configurable APIs like `context`, `beforeLoad`, `loaderDeps` and `loader` work in unison to make it easy to define declarative data dependencies, prefetch data, and manage the lifecycle of an external data source with ease. + +## Inherited Route Context + +TanStack Router's router and route context is a powerful feature that allows you to define context that is specific to a route which is then inherited by all child routes. Even the router and root routes themselves can provide context. Context can be built up both synchronously and asynchronously, and can be used to share data, configuration, or even functions between routes and route configurations. This is especially useful for scenarios like: + +- Authentication and Authorization +- Hybrid SSR/CSR data fetching and preloading +- Theming +- Singletons and global utilities +- Curried or partial application across preloading, loading, and rendering stages + +Also, what would route context be if it weren't type-safe? TanStack Router's route context is fully type-safe and inferred at zero cost to you. + +## File-based and/or Code-Based Routing + +TanStack Router supports both file-based and code-based routing at the same time. This flexibility allows you to choose the approach that best fits your project's needs. + +TanStack Router's file-based routing approach is uniquely user-facing. Route configuration is generated for you either by the Vite plugin or TanStack Router CLI, leaving the usage of said generated code up to you! This means that you're always in total control of your routes and router, even if you use file-based routing. + +## Acknowledgements + +TanStack Router builds on concepts and patterns popularized by many other OSS projects, including: + +- [TRPC](https://trpc.io/) +- [Remix](https://remix.run) +- [Chicane](https://swan-io.github.io/chicane/) +- [Next.js](https://nextjs.org) + +We acknowledge the investment, risk and research that went into their development, but are excited to push the bar they have set even higher. + +## Let's go! + +Enough overview, there's so much more to do with TanStack Router. Hit that next button and let's get started! diff --git a/docs/router/framework/solid/quick-start.md b/docs/router/framework/solid/quick-start.md new file mode 100644 index 00000000000..aa91cab3efd --- /dev/null +++ b/docs/router/framework/solid/quick-start.md @@ -0,0 +1,217 @@ +--- +title: Quick Start +--- + +If you're feeling impatient and prefer to skip all of our wonderful documentation, here is the bare minimum to get going with TanStack Router using both file-based route generation and code-based route configuration: + +## Using File-Based Route Generation + +File based route generation (through Vite, and other supported bundlers) is the recommended way to use TanStack Router as it provides the best experience, performance, and ergonomics for the least amount of effort. + +### Manual Setup + +Alternatively, you can manually setup the project using the following steps: + +#### Install TanStack Router, Vite Plugin + +```sh +npm install @tanstack/solid-router +npm install -D @tanstack/router-plugin +# or +pnpm add @tanstack/solid-router +pnpm add -D @tanstack/router-plugin +# or +yarn add @tanstack/solid-router +yarn add -D @tanstack/router-plugin +# or +bun add @tanstack/solid-router +bun add -D @tanstack/router-plugin +# or +deno add npm:@tanstack/solid-router npm:@tanstack/router-plugin +``` + +#### Configure the Vite Plugin + +```tsx +// vite.config.ts +import { defineConfig } from 'vite' +import solid from 'vite-plugin-solid' +import { TanStackRouterVite } from '@tanstack/router-plugin/vite' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + TanStackRouterVite({ target: 'solid', autoCodeSplitting: true }), + solid(), + // ..., + ], +}) +``` + +> [!TIP] +> If you are not using Vite, or any of the supported bundlers, you can check out the [TanStack Router CLI](./guide/file-based-routing.md#configuration-with-the-tanstack-router-cli) guide for more info. + +Create the following files: + +- `src/routes/__root.tsx` +- `src/routes/index.tsx` +- `src/routes/about.tsx` +- `src/main.tsx` + +#### `src/routes/__root.tsx` + +```tsx +import { createRootRoute, Link, Outlet } from '@tanstack/solid-router' + +export const Route = createRootRoute({ + component: () => ( + <> +
+ + Home + {' '} + + About + +
+
+ + + ), +}) +``` + +#### `src/routes/index.tsx` + +```tsx +import { createLazyFileRoute } from '@tanstack/solid-router' + +export const Route = createLazyFileRoute('/')({ + component: Index, +}) + +function Index() { + return ( +
+

Welcome Home!

+
+ ) +} +``` + +#### `src/routes/about.tsx` + +```tsx +import { createLazyFileRoute } from '@tanstack/solid-router' + +export const Route = createLazyFileRoute('/about')({ + component: About, +}) + +function About() { + return
Hello from About!
+} +``` + +#### `src/main.tsx` + +Regardless of whether you are using the `@tanstack/router-plugin` package and running the `npm run dev`/`npm run build` scripts, or manually running the `tsr watch`/`tsr generate` commands from your package scripts, the route tree file will be generated at `src/routeTree.gen.ts`. + +Import the generated route tree and create a new router instance: + +```tsx +import { render } from 'solid-js/web' +import { RouterProvider, createRouter } from '@tanstack/solid-router' + +// Import the generated route tree +import { routeTree } from './routeTree.gen' + +// Create a new router instance +const router = createRouter({ routeTree }) + +// Register the router instance for type safety +declare module '@tanstack/solid-router' { + interface Register { + router: typeof router + } +} + +// Render the app +const rootElement = document.getElementById('root')! +if (!rootElement.innerHTML) { + render(() => , rootElement) +} +``` + +If you are working with this pattern you should change the `id` of the root `
` on your `index.html` file to `
` + +## Using Code-Based Route Configuration + +> [!IMPORTANT] +> The following example shows how to configure routes using code, and for simplicity's sake is in a single file for this demo. While code-based generation allows you to declare many routes and even the router instance in a single file, we recommend splitting your routes into separate files for better organization and performance as your application grows. + +```tsx +import { render } from 'solid-js/web' +import { + Outlet, + RouterProvider, + Link, + createRouter, + createRoute, + createRootRoute, +} from '@tanstack/solid-router' + +const rootRoute = createRootRoute({ + component: () => ( + <> +
+ + Home + {' '} + + About + +
+
+ + + ), +}) + +const indexRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/', + component: function Index() { + return ( +
+

Welcome Home!

+
+ ) + }, +}) + +const aboutRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/about', + component: function About() { + return
Hello from About!
+ }, +}) + +const routeTree = rootRoute.addChildren([indexRoute, aboutRoute]) + +const router = createRouter({ routeTree }) + +declare module '@tanstack/solid-router' { + interface Register { + router: typeof router + } +} + +const rootElement = document.getElementById('app')! +if (!rootElement.innerHTML) { + render(() => , rootElement) +} +``` + +If you glossed over these examples or didn't understand something, we don't blame you, because there's so much more to learn to really take advantage of TanStack Router! Let's move on.