Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
28 changes: 22 additions & 6 deletions docs/framework/react/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,23 @@ If you're feeling impatient and prefer to skip all of our wonderful documentatio

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.

### Install the Vite Plugin and the Router Devtools
### Scaffolding Your First TanStack Router Project

```bash
npm create @tanstack/router@latest
# or
pnpm create @tanstack/router
# or
yarn create @tanstack/router
# or
bun create @tanstack/router
```

Follow the prompts to setup the project.

### Manual Setup

#### Install the Vite Plugin and the Router Devtools

```bash
npm i -D @tanstack/router-plugin @tanstack/router-devtools
Expand All @@ -20,7 +36,7 @@ yarn add -D @tanstack/router-plugin @tanstack/router-devtools
bun add -D @tanstack/router-plugin @tanstack/router-devtools
```

### Configure the Vite Plugin
#### Configure the Vite Plugin

```tsx
// vite.config.ts
Expand Down Expand Up @@ -50,7 +66,7 @@ Create the following files:

> 🧠 Route files with the `.lazy.tsx` extension are lazy loaded via separate bundles to keep the main bundle size as lean as possible.

### `src/routes/__root.tsx`
#### `src/routes/__root.tsx`

```tsx
import { createRootRoute, Link, Outlet } from '@tanstack/react-router'
Expand All @@ -75,7 +91,7 @@ export const Route = createRootRoute({
})
```

### `src/routes/index.lazy.tsx`
#### `src/routes/index.lazy.tsx`

```tsx
import { createLazyFileRoute } from '@tanstack/react-router'
Expand All @@ -93,7 +109,7 @@ function Index() {
}
```

### `src/routes/about.lazy.tsx`
#### `src/routes/about.lazy.tsx`

```tsx
import { createLazyFileRoute } from '@tanstack/react-router'
Expand All @@ -107,7 +123,7 @@ function About() {
}
```

### `src/main.tsx`
#### `src/main.tsx`

Regardless if you are using the `@tanstack/router-plugin` package or manually running the `tsr watch`/`tsr generate` commands from your package scripts, the following file will be generated for you at `src/routeTree.gen.ts`.

Expand Down
2 changes: 1 addition & 1 deletion examples/react/quickstart-rspack-file-based/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"type": "module",
"scripts": {
"dev": "rsbuild dev --port 3001",
"build": "rsbuild build",
"build": "rsbuild build && tsc --noEmit",
"preview": "rsbuild preview"
},
"dependencies": {
Expand Down
2 changes: 1 addition & 1 deletion examples/react/quickstart-webpack-file-based/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"type": "module",
"scripts": {
"dev": "webpack serve --port 3001 --no-open",
"build": "webpack build"
"build": "webpack build && tsc --noEmit"
},
"dependencies": {
"@tanstack/react-router": "^1.56.5",
Expand Down
13 changes: 13 additions & 0 deletions packages/create-router/build.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { defineBuildConfig } from 'unbuild'

export default defineBuildConfig({
entries: ['src/index'],
clean: true,
rollup: {
inlineDependencies: true,
esbuild: {
target: 'node18',
minify: true,
},
},
})
5 changes: 5 additions & 0 deletions packages/create-router/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// @ts-check

import rootConfig from '../../eslint.config.js'

export default [...rootConfig]
3 changes: 3 additions & 0 deletions packages/create-router/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env node

import './dist/index.mjs'
120 changes: 120 additions & 0 deletions packages/create-router/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
{
"name": "@tanstack/create-router",
"version": "1.56.0",
"description": "Modern and scalable routing for React applications",
"author": "Tanner Linsley",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/TanStack/router.git",
"directory": "packages/create-router"
},
"homepage": "https://tanstack.com/router",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"bin": {
"create-router": "index.js"
},
"scripts": {
"dev": "unbuild --stub",
"clean": "rimraf ./dist && rimraf ./coverage",
"test:eslint": "eslint ./src",
"build": "unbuild"
},
"type": "module",
"files": [
"index.js",
"templates",
"dist"
],
"engines": {
"node": "^18.0.0 || >=20.0.0"
},
"devDependencies": {
"@inquirer/prompts": "^5.5.0",
"@types/cross-spawn": "^6.0.6",
"@types/validate-npm-package-name": "^4.0.2",
"commander": "^12.1.0",
"cross-spawn": "^7.0.3",
"fast-glob": "^3.3.2",
"picocolors": "^1.1.0",
"unbuild": "^2.0.0",
"validate-npm-package-name": "^5.0.1",
"yocto-spinner": "^0.1.0"
},
"peerDependencies": {
"@rsbuild/core": "1.0.1-rc.0",
"@rsbuild/plugin-react": "1.0.1-rc.0",
"@swc/core": "^1.7.6",
"@tanstack/react-router": "workspace:*",
"@tanstack/router-devtools": "workspace:*",
"@tanstack/router-plugin": "workspace:*",
"@types/react": "^18.2.47",
"@types/react-dom": "^18.2.18",
"@vitejs/plugin-react": "^4.3.1",
"html-webpack-plugin": "^5.6.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"swc-loader": "^0.2.6",
"typescript": "^5.5.3",
"vite": "^5.4.3",
"webpack": "^5.93.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^5.0.4"
},
"peerDependenciesMeta": {
"@tanstack/react-router": {
"optional": true
},
"@tanstack/router-devtools": {
"optional": true
},
"@tanstack/router-plugin": {
"optional": true
},
"@vitejs/plugin-react": {
"optional": true
},
"vite": {
"optional": true
},
"@swc/core": {
"optional": true
},
"html-webpack-plugin": {
"optional": true
},
"swc-loader": {
"optional": true
},
"webpack": {
"optional": true
},
"webpack-cli": {
"optional": true
},
"webpack-dev-server": {
"optional": true
},
"@rsbuild/core": {
"optional": true
},
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
},
"typescript": {
"optional": true
},
"react": {
"optional": true
},
"react-dom": {
"optional": true
}
}
}
16 changes: 16 additions & 0 deletions packages/create-router/src/bundler/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { apply as applyVite } from './vite'
import { apply as applyRspack } from './rspack'
import { apply as applyWebpack } from './webpack'
import type { Bundler } from '../constants'
import type { ApplyParams } from '../types'

export function apply(bundler: Bundler, params: ApplyParams) {
switch (bundler) {
case 'vite':
return applyVite(params)
case 'rspack':
return applyRspack(params)
case 'webpack':
return applyWebpack(params)
}
}
33 changes: 33 additions & 0 deletions packages/create-router/src/bundler/rspack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { copyTemplateFiles } from '../utils/copyTemplateFiles'
import type { ApplyParams, BundlerResult, PeerDependency } from '../types'

export const scripts = {
dev: 'rsbuild dev --port 3001',
build: 'rsbuild build',
preview: 'rsbuild preview',
} as const

export const devDependencies = [
'@rsbuild/core',
'@rsbuild/plugin-react',
] as const satisfies Array<PeerDependency>

export const overrides = {
'@tanstack/router-plugin': {
'@rsbuild/core': '$@rsbuild/core',
},
}
export async function apply({
targetFolder,
}: ApplyParams): Promise<BundlerResult> {
await copyTemplateFiles({
file: '**/*',
sourceFolder: 'bundler/rspack',
targetFolder,
})
return {
scripts,
devDependencies,
overrides,
}
}
28 changes: 28 additions & 0 deletions packages/create-router/src/bundler/vite.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { copyTemplateFiles } from '../utils/copyTemplateFiles'
import type { ApplyParams, BundlerResult, PeerDependency } from '../types'

export const scripts = {
dev: 'vite --port=3001',
build: 'vite build',
serve: 'vite preview',
start: 'vite',
} as const

export const devDependencies = [
'@vitejs/plugin-react',
'vite',
] as const satisfies Array<PeerDependency>

export async function apply({
targetFolder,
}: ApplyParams): Promise<BundlerResult> {
await copyTemplateFiles({
file: '**/*',
sourceFolder: 'bundler/vite',
targetFolder,
})
return {
scripts,
devDependencies,
}
}
30 changes: 30 additions & 0 deletions packages/create-router/src/bundler/webpack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { copyTemplateFiles } from '../utils/copyTemplateFiles'
import type { ApplyParams, BundlerResult, PeerDependency } from '../types'

export const scripts = {
dev: 'webpack serve --port 3001 --no-open',
build: 'webpack build',
} as const

export const devDependencies = [
'@swc/core',
'html-webpack-plugin',
'swc-loader',
'webpack',
'webpack-cli',
'webpack-dev-server',
] as const satisfies Array<PeerDependency>

export async function apply({
targetFolder,
}: ApplyParams): Promise<BundlerResult> {
await copyTemplateFiles({
file: '**/*',
sourceFolder: 'bundler/webpack',
targetFolder,
})
return {
scripts,
devDependencies,
}
}
Loading