Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: updated tanstack router example #236

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ docs/.vitepress/cache
tmp

.DS_Store
.idea
123 changes: 44 additions & 79 deletions examples/react/ssr/tanstack-router-app/app.config.js
Original file line number Diff line number Diff line change
@@ -1,100 +1,65 @@
import { TanStackRouterVite } from "@tanstack/router-vite-plugin";
import { serverFunctions } from "@vinxi/server-functions/plugin";
import { serverTransform } from "@vinxi/server-functions/server";
import reactRefresh from "@vitejs/plugin-react";
import { join } from "path";
import { createApp, resolve } from "vinxi";
import {
BaseFileSystemRouter,
analyzeModule,
cleanPath,
} from "vinxi/fs-router";
import { resolve } from "import-meta-resolve";
import * as path from "path";
import { createApp } from "vinxi";

function tanstackFileRouter(config) {
class TanstackFileRouter extends BaseFileSystemRouter {
glob() {
return join(this.config.dir, "**/(page|layout).tsx");
}
toPath(src) {
const routePath = cleanPath(src, this.config)
// remove the initial slash
.replace(/\/page$/, "/")
.replace(/\/layout$/, "")
.replace(/index$/, "")
.replace(/\[([^\/]+)\]/g, (_, m) => {
if (m.length > 3 && m.startsWith("...")) {
return `*${m.slice(3)}`;
}
if (m.length > 2 && m.startsWith("[") && m.endsWith("]")) {
return `$${m.slice(1, -1)}?`;
}
return `$${m}`;
});
const resolveToRelative = (p) => {
const toAbsolute = (file) => file.split("://").at(-1);

return routePath?.length > 0 ? `${routePath}` : "/";
}
const resolved = toAbsolute(resolve(p, import.meta.url));

toRoute(src) {
let path = this.toPath(src);
const relative = path.relative(
path.resolve(toAbsolute(import.meta.url), ".."),
resolved,
);

const [_, exports] = analyzeModule(src);
const hasLoader = exports.find((e) => e.n === "loader");
const hasErrorBoundary = exports.find((e) => e.n === "ErrorBoundary");
const hasLoading = exports.find((e) => e.n === "Loading");
const hasConfig = exports.find((e) => e.n === "config");
return {
$component: {
src: src,
pick: ["default", "$css"],
},
$error: hasErrorBoundary
? { src: src, pick: ["ErrorBoundary"] }
: undefined,
$loading: hasLoading ? { src: src, pick: ["Loading"] } : undefined,
$$loader: hasLoader
? {
src: src,
pick: ["loader"],
}
: undefined,
$$config: hasConfig ? { src: src, pick: ["config"] } : undefined,
path,
filePath: src,
};
}
}

return (router, app) =>
new TanstackFileRouter(
{
dir: resolve.absolute(config.dir, router.root),
extensions: config.extensions ?? ["ts", "tsx", "jsx", "js"],
},
router,
app,
);
}
return relative;
};

export default createApp({
server: {},
routers: [
{
name: "public",
type: "static",
Copy link
Owner

Choose a reason for hiding this comment

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

i don't think this is correct, the new API is "type", "mode" is old, i think you will have to bump to vinxi": "0.3.9", and make it work with that

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done, thanks. Should the validation schema not throw if it is being passed a wrong option tho? Or if it is for backwards compatibility reasons to at least print a deprecation warning.

Copy link
Owner

Choose a reason for hiding this comment

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

Yeah I think makes sense to do a deprecation warning, I just don't want to add those while we are still in 0.x.x versions, coz things are changing and can't add notices for everything, the validation should error (but I think for now we accepted both until I remove one) okay yeah maybe then a deprecation warning is a good idea, I think i will remove the option and just error in the validation)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great, yeah erroring sounds good to me

dir: "./public",
},
{
name: "client",
type: "client",
handler: "./app/client.tsx",
routes: tanstackFileRouter({ dir: "./app/routes" }),
target: "browser",
plugins: () => [reactRefresh()],
base: "/",
},
{
name: "ssr",
type: "http",
handler: "./app/server.tsx",
routes: tanstackFileRouter({ dir: "./app/routes" }),
target: "server",
plugins: () => [reactRefresh()],
plugins: () => [
reactRefresh(),
serverTransform({
runtime: `@tanstack/react-router-server/server-runtime`,
}),
TanStackRouterVite(),
],
},
{
name: "client",
type: "client",
handler: "./app/client.tsx",
target: "browser",
plugins: () => [
serverFunctions.client({
runtime: `@tanstack/react-router-server/client-runtime`,
}),
reactRefresh(),
TanStackRouterVite(),
],
base: "/_build",
},
serverFunctions.router({
name: "server",
handler: resolveToRelative(
"@tanstack/react-router-server/server-handler",
),
runtime: `@tanstack/react-router-server/server-runtime`,
}),
],
});
65 changes: 32 additions & 33 deletions examples/react/ssr/tanstack-router-app/app/client.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,37 @@
/// <reference types="vinxi/types/client" />
import { StartClient } from "@tanstack/react-start/client";
import { createAssets } from "@vinxi/react";
import ReactDOM from "react-dom/client";
import "vinxi/client";
import { getManifest } from "vinxi/manifest";
import { Root, hydrateRoot } from 'react-dom/client'
import 'vinxi/client'

import { createRouter } from "./router";
import "./style.css";
import { createRouter } from './router'
import { StartClient } from '@tanstack/react-router-server/client'

const Assets = createAssets(
getManifest("client").handler,
getManifest("client"),
);
render()

const router = createRouter(getManifest("client"), undefined);
router.update({
context: {
...router.context,
assets: (
<>
<Assets />
{import.meta.env.DEV ? (
<script
src={
getManifest("client").inputs[getManifest("client").handler].output
.path
}
type="module"
/>
) : null}
</>
),
},
});
router.hydrate();
function render(mod?: any) {
const router = createRouter()

ReactDOM.hydrateRoot(document, <StartClient router={router} />);
const app = <StartClient router={router} />

if (!mod) {
// Initial
router.hydrate()
window.$root = hydrateRoot(document, app)
} else {
// Hot
window.$root?.render(app)
}
}

if (import.meta.hot) {
import.meta.hot.accept((mod) => {
if (mod) {
render(mod)
}
})
}

declare global {
interface Window {
$root?: Root
}
}
35 changes: 0 additions & 35 deletions examples/react/ssr/tanstack-router-app/app/loaderClient.tsx

This file was deleted.

84 changes: 84 additions & 0 deletions examples/react/ssr/tanstack-router-app/app/routeTree.gen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/* prettier-ignore-start */

/* eslint-disable */

// @ts-nocheck

// noinspection JSUnusedGlobalSymbols

// This file is auto-generated by TanStack Router

// Import Routes

import { Route as rootRoute } from './routes/__root'
import { Route as IndexImport } from './routes/index'
import { Route as PostsIndexImport } from './routes/posts_/index'
import { Route as HelloIndexImport } from './routes/hello/index'
import { Route as PostslayoutImport } from './routes/posts_/_layout'
import { Route as PostsPostIdImport } from './routes/posts_/$postId'

// Create/Update Routes

const IndexRoute = IndexImport.update({
path: '/',
getParentRoute: () => rootRoute,
} as any)

const PostsIndexRoute = PostsIndexImport.update({
path: '/posts/',
getParentRoute: () => rootRoute,
} as any)

const HelloIndexRoute = HelloIndexImport.update({
path: '/hello/',
getParentRoute: () => rootRoute,
} as any)

const PostslayoutRoute = PostslayoutImport.update({
path: '/posts/_layout',
getParentRoute: () => rootRoute,
} as any)

const PostsPostIdRoute = PostsPostIdImport.update({
path: '/posts/$postId',
getParentRoute: () => rootRoute,
} as any)

// Populate the FileRoutesByPath interface

declare module '@tanstack/react-router' {
interface FileRoutesByPath {
'/': {
preLoaderRoute: typeof IndexImport
parentRoute: typeof rootRoute
}
'/posts/$postId': {
preLoaderRoute: typeof PostsPostIdImport
parentRoute: typeof rootRoute
}
'/posts/_layout': {
preLoaderRoute: typeof PostslayoutImport
parentRoute: typeof rootRoute
}
'/hello/': {
preLoaderRoute: typeof HelloIndexImport
parentRoute: typeof rootRoute
}
'/posts/': {
preLoaderRoute: typeof PostsIndexImport
parentRoute: typeof rootRoute
}
}
}

// Create and export the route tree

export const routeTree = rootRoute.addChildren([
IndexRoute,
PostsPostIdRoute,
PostslayoutRoute,
HelloIndexRoute,
PostsIndexRoute,
])

/* prettier-ignore-end */
Loading