Skip to content

Commit

Permalink
checkpoint: no more pending
Browse files Browse the repository at this point in the history
  • Loading branch information
tannerlinsley committed Nov 15, 2022
1 parent 8f923bf commit 853bbe8
Show file tree
Hide file tree
Showing 64 changed files with 844 additions and 311 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

.vite
# See https://help.github.com/ignore-files/ for more about ignoring files.

# dependencies
Expand Down
6 changes: 2 additions & 4 deletions docs/api/frameworks.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ The `FrameworksGenerics` interface is available for framework adapters to extend

Primarily these include:

- Element
- SyncOrAsyncElement
- Component

Internally, the `GetFrameworkGeneric` function is used to retrieve these generics.

Expand All @@ -19,8 +18,7 @@ export interface FrameworkGenerics {
// and are extended by framework adapters, but cannot be
// pre-defined as constraints:
//
// Element: any
// SyncOrAsyncElement?: any
// Component: any
}

export type GetFrameworkGeneric<U> = U extends keyof FrameworkGenerics
Expand Down
6 changes: 3 additions & 3 deletions docs/guide/layout-routes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
title: Layout Routes
---

Layout routes are routes that do not have a path, but allows wrapping it's child routes with wrapper elements or shared logic. Layout routes are useful for:
Layout routes are routes that do not have a path, but allows wrapping it's child routes with wrapper components or shared logic. Layout routes are useful for:

- Wrapping child routes with a layout element
- Wrapping child routes with a layout component
- Sharing a loader between all of the child routes
- Sharing search params between all of the child routes
- Sharing a error element with all child routes
- Sharing an error component with all child routes

To create a layout route, define a route config with an `id` property instead of a `path`:

Expand Down
4 changes: 2 additions & 2 deletions docs/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ import {
const routeConfig = createRouteConfig().createChildren((createRoute) => [
createRoute({
path: '/',
element: <Index />,
component: Index,
}),
createRoute({
path: 'about',
element: <About />,
component: About,
}),
])

Expand Down
5 changes: 5 additions & 0 deletions examples/react/basic-ssr-lite/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
.DS_Store
dist
dist-ssr
*.local
6 changes: 6 additions & 0 deletions examples/react/basic-ssr-lite/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Example

To run this example:

- `npm install` or `yarn`
- `yarn start` or `yarn start`
13 changes: 13 additions & 0 deletions examples/react/basic-ssr-lite/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
<!--app-head-->
</head>
<body>
<div id="root"><!--app-html--></div>
<script type="module" src="/src/entry-client.tsx"></script>
</body>
</html>
33 changes: 33 additions & 0 deletions examples/react/basic-ssr-lite/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "tanstack-router-react-example-basic-ssr-lite",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "node server",
"build": "npm run build:client && npm run build:server",
"build:client": "vite build --outDir dist/client",
"build:server": "vite build --ssr src/entry-server.jsx --outDir dist/server",
"serve": "NODE_ENV=production node server",
"debug": "node --inspect-brk server"
},
"dependencies": {
"@tanstack/react-router": "0.0.1-beta.11",
"@tanstack/react-router-devtools": "0.0.1-beta.10",
"axios": "^1.1.3",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@babel/core": "^7.20.2",
"@rollup/plugin-babel": "^6.0.2",
"@types/jsesc": "^3.0.1",
"@vitejs/plugin-react": "^2.2.0",
"compression": "^1.7.4",
"express": "^4.18.2",
"jsesc": "^3.0.2",
"serve-static": "^1.15.0",
"vite": "^3.2.3",
"vite-plugin-babel": "^1.1.2"
}
}
110 changes: 110 additions & 0 deletions examples/react/basic-ssr-lite/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import express from 'express'

const __dirname = path.dirname(fileURLToPath(import.meta.url))

const isTest = process.env.NODE_ENV === 'test' || !!process.env.VITE_TEST_BUILD

process.env.MY_CUSTOM_SECRET = 'API_KEY_qwertyuiop'

export async function createServer(
root = process.cwd(),
isProd = process.env.NODE_ENV === 'production',
hmrPort,
) {
const resolve = (p) => path.resolve(__dirname, p)

const indexProd = isProd
? fs.readFileSync(resolve('dist/client/index.html'), 'utf-8')
: ''

const app = express()

/**
* @type {import('vite').ViteDevServer}
*/
let vite
if (!isProd) {
vite = await (
await import('vite')
).createServer({
root,
logLevel: isTest ? 'error' : 'info',
server: {
middlewareMode: true,
watch: {
// During tests we edit the files too fast and sometimes chokidar
// misses change events, so enforce polling for consistency
usePolling: true,
interval: 100,
},
hmr: {
port: hmrPort,
},
},
appType: 'custom',
})
// use vite's connect instance as middleware
app.use(vite.middlewares)
} else {
app.use((await import('compression')).default())
app.use(
(await import('serve-static')).default(resolve('dist/client'), {
index: false,
}),
)
}

app.use('*', async (req, res) => {
try {
const url = req.originalUrl

if (url.includes('.')) {
console.warn(`${url} is not valid router path`)
return res.status(404)
}

let template, render

if (!isProd) {
// always read fresh template in dev
template = fs.readFileSync(resolve('index.html'), 'utf-8')
template = await vite.transformIndexHtml(url, template)
render = (await vite.ssrLoadModule('/src/entry-server.tsx')).render
} else {
template = indexProd
render = (await import('./dist/server/entry-server.tsx')).render
}

const context = {}
const [appHead, appHtml] = await render(url, context)

if (context.url) {
// Somewhere a `<Redirect>` was rendered
return res.redirect(301, context.url)
}

const html = template
.replace('<!--app-head-->', appHead)
.replace(`<!--app-html-->`, appHtml)

res.status(200).set({ 'Content-Type': 'text/html' }).end(html)
} catch (e) {
!isProd && vite.ssrFixStacktrace(e)
console.log(e.stack)
res.status(500).end(e.stack)
}
})

return { app, vite }
}

if (!isTest) {
createServer().then(({ app }) =>
app.listen(3000, () => {
console.log('Client Server: http://localhost:3000')
}),
)
}
35 changes: 35 additions & 0 deletions examples/react/basic-ssr-lite/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import * as React from 'react'
import { Outlet } from '@tanstack/react-router'
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'

import { router } from './router'

export function App() {
return (
// Build our routes and render our router
<>
<div>
<router.Link
to="/"
activeProps={{
className: 'font-bold',
}}
activeOptions={{ exact: true }}
>
Home
</router.Link>{' '}
<router.Link
to="/posts"
activeProps={{
className: 'font-bold',
}}
>
Posts
</router.Link>
</div>
<hr />
<Outlet />
<TanStackRouterDevtools router={router} />
</>
)
}
23 changes: 23 additions & 0 deletions examples/react/basic-ssr-lite/src/entry-client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as React from 'react'
import ReactDOM from 'react-dom/client'
import { RouterProvider } from '@tanstack/react-router'

import { router } from './router'
import { App } from './App'

const state = (window as any).__TANSTACK_ROUTER_STATE__

router.hydrateState(state)

ReactDOM.hydrateRoot(
document.getElementById('root')!,
<RouterProvider router={router}>
<App />
</RouterProvider>,
)

// ReactDOM.createRoot(document.getElementById('root')!).render(
// <RouterProvider router={router}>
// <App />
// </RouterProvider>,
// )
42 changes: 42 additions & 0 deletions examples/react/basic-ssr-lite/src/entry-server.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import * as React from 'react'
import ReactDOMServer from 'react-dom/server'
import { createMemoryHistory, RouterProvider } from '@tanstack/react-router'
import jsesc from 'jsesc'
import { App } from './App'
import { router } from './router'

export async function render(url: string) {
const memoryHistory = createMemoryHistory({
initialEntries: [url],
})

router.update({
history: memoryHistory,
})

const unsub = router.mount()
await router.load()

const routerState = router.dehydrateState()

const res = [
`<script>window.__TANSTACK_ROUTER_STATE__ = JSON.parse(${jsesc(
JSON.stringify(routerState),
{
isScriptContext: true,
wrap: true,
json: true,
},
)})</script>`,
ReactDOMServer.renderToString(
<RouterProvider router={router}>
<App />
</RouterProvider>,
),
]

unsub()
router.reset()

return res
}
Loading

0 comments on commit 853bbe8

Please sign in to comment.