-
-
Notifications
You must be signed in to change notification settings - Fork 92
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: streaming rendering with Suspense boundaries as flush trigger (#…
…296) * Disable eslint lines-around-comment rule * Update test scripts to allow watch usage * Add streaming renderer * Switch to element nodes as markers instead * Switch away from global ids * Remove subtree option * feat: use comments instead of element as marker feat: use custom element for hydration feat: add onError to renderToChunks feat: add renderToPipeableStream * chore: use NodeIterator to locate comments This reduces code and *should* also be more performant than recursive JS iteration. See: https://developer.mozilla.org/en-US/docs/Web/API/NodeIterator * chore: remove redundancy and minify code * more minification * even more minification * Move files to new test dir structure * Fix linting error * fix ts types * fix Web Streams tests on Node <18 * Streaming renderer: factor chunking out of main entrypoint and rebase on #241 (#267) * use index.module.js when benchmarking, since its the output of `npm run transpile` * fix bench:v8 output path * update microbundle and turn off function inlining * fix JSX entrypoint and tests * fix type defintion to reflect removed exports and options * fix root copy of jsx types * optimize renderToString performance using switch and short-circuiting * Create bright-ligers-jam.md * Update bright-ligers-jam.md * Update bright-ligers-jam.md * Backport changes from #237 (child/parent properties, simplified Fragment handling) * ci: update github actions (#266) * ci: update actions/checkout to v3 * ci: update actions/cache to v3 * merge master * lockfile version * update benchmarking reference implmementation to 5.2.6 (6a0bec2) * fix tests * fix before diff hook being called on invalid vnodes * move non-exported files into a lib directory * update pretty implementation and move typedefs into a d.ts * Move chunked implementation out of the default entrypoint * update tests to reflect chunking being moved out of default entrypoint * fix d8 bench script --------- Co-authored-by: Abdul Rauf <[email protected]> * fix d8 bench path * try new way of getting mask as we are not setting it anymore * stop interfering with the real useId * show bug * partial fix * continuously fork promises * fix tests * fixes * update lockfiles * Create twelve-candles-walk.md * add build command * fix rebase issues * address comments * bump deps --------- Co-authored-by: Marvin Hagemeister <[email protected]> Co-authored-by: Jacob Ebey <[email protected]> Co-authored-by: Jason Miller <[email protected]> Co-authored-by: Jason Miller <[email protected]> Co-authored-by: Abdul Rauf <[email protected]>
- Loading branch information
1 parent
f510fa5
commit 0faec39
Showing
30 changed files
with
27,971 additions
and
25,847 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'preact-render-to-string': minor | ||
--- | ||
|
||
Introduce a streaming renderer which can be imported from `preact-render-to-string/stream` and `preact-render-to-string/stream-node` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"preact-render-to-string": patch | ||
--- | ||
|
||
streaming rendering with Suspense boundaries as flush trigger |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<!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> | ||
</head> | ||
<body> | ||
<div id="app"><!--app-html--></div> | ||
<script type="module" src="/src/entry-client.jsx"></script> | ||
</body> | ||
</html> |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
{ | ||
"name": "demo", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "server.js", | ||
"type": "module", | ||
"scripts": { | ||
"dev": "vite --force", | ||
"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" | ||
}, | ||
"author": "", | ||
"license": "ISC", | ||
"devDependencies": { | ||
"vite": "^4.1.4" | ||
}, | ||
"dependencies": { | ||
"@preact/preset-vite": "^2.8.0", | ||
"express": "^4.18.2", | ||
"graphql": "^16.6.0", | ||
"preact": "^10.21.0", | ||
"urql": "latest" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { h } from 'preact'; | ||
import { Suspense, lazy } from 'preact/compat'; | ||
import { Client, Provider, cacheExchange, fetchExchange } from 'urql'; | ||
|
||
const client = new Client({ | ||
url: 'https://trygql.formidable.dev/graphql/basic-pokedex', | ||
exchanges: [cacheExchange, fetchExchange], | ||
suspense: true | ||
}); | ||
|
||
export function App({ head }) { | ||
const Pokemons = lazy( | ||
() => | ||
new Promise((res) => { | ||
setTimeout( | ||
() => { | ||
res(import('./Pokemons.jsx')); | ||
}, | ||
typeof document === 'undefined' ? 500 : 3000 | ||
); | ||
}) | ||
); | ||
return ( | ||
<html> | ||
<head dangerouslySetInnerHTML={{ __html: head }} /> | ||
<body> | ||
<Provider value={client}> | ||
<main> | ||
<h1>Our Counter application</h1> | ||
<Suspense fallback={<p>Loading...</p>}> | ||
<Pokemons /> | ||
</Suspense> | ||
</main> | ||
{import.meta.env.DEV && ( | ||
<script type="module" src="/src/entry-client.jsx" /> | ||
)} | ||
</Provider> | ||
</body> | ||
</html> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { gql, useQuery } from 'urql'; | ||
import { h } from 'preact'; | ||
|
||
const POKEMONS_QUERY = gql` | ||
query Pokemons($limit: Int!) { | ||
pokemons(limit: $limit) { | ||
id | ||
name | ||
} | ||
} | ||
`; | ||
|
||
const Counter = () => { | ||
const [result] = useQuery({ | ||
query: POKEMONS_QUERY, | ||
variables: { limit: 10 } | ||
}); | ||
|
||
const { data, fetching, error } = result; | ||
console.log('hydrated!'); | ||
return ( | ||
<div> | ||
{fetching && <p>Loading...</p>} | ||
|
||
{error && <p>Oh no... {error.message}</p>} | ||
|
||
{data && ( | ||
<ul> | ||
{data.pokemons.map((pokemon) => ( | ||
<li key={pokemon.id}>{pokemon.name}</li> | ||
))} | ||
</ul> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
export default Counter; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { hydrate } from 'preact'; | ||
import { App } from './App'; | ||
|
||
const config = { attributes: true, childList: true, subtree: true }; | ||
const mut = new MutationObserver((mutationList, observer) => { | ||
for (const mutation of mutationList) { | ||
if (mutation.type === 'childList') { | ||
console.log('A child node has been added or removed.', mutation); | ||
} else if (mutation.type === 'attributes') { | ||
console.log( | ||
`The ${mutation.attributeName} attribute was modified.`, | ||
mutation | ||
); | ||
} | ||
} | ||
}); | ||
mut.observe(document, config); | ||
|
||
hydrate(<App />, document); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { renderToPipeableStream } from '../../src/stream-node'; | ||
import { App } from './App'; | ||
|
||
export function render({ res, head }) { | ||
res.socket.on('error', (error) => { | ||
console.error('Fatal', error); | ||
}); | ||
const { pipe, abort } = renderToPipeableStream(<App head={head} />, { | ||
onShellReady() { | ||
res.statusCode = 200; | ||
res.setHeader('Content-type', 'text/html'); | ||
pipe(res); | ||
}, | ||
onErrorShell(error) { | ||
res.statusCode = 500; | ||
res.send( | ||
`<!doctype html><p>An error ocurred:</p><pre>${error.message}</pre>` | ||
); | ||
} | ||
}); | ||
|
||
// Abandon and switch to client rendering if enough time passes. | ||
// Try lowering this to see the client recover. | ||
setTimeout(abort, 20000); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { defineConfig } from 'vite'; | ||
import preact from '@preact/preset-vite'; | ||
import path from 'path'; | ||
import { promises as fs } from 'fs'; | ||
|
||
function ssrPlugin() { | ||
return { | ||
name: 'ssrPlugin', | ||
|
||
configureServer(server) { | ||
server.middlewares.use(async (req, res, next) => { | ||
if (req.url !== '/') { | ||
return next(); | ||
} | ||
|
||
const { render } = await server.ssrLoadModule( | ||
path.resolve(__dirname, './src/entry-server') | ||
); | ||
|
||
// setTimeout(abort, 10000); | ||
|
||
const indexHtml = await fs.readFile( | ||
path.resolve(__dirname, './index.html'), | ||
'utf-8' | ||
); | ||
|
||
const url = new URL('http://localhost:5173/' + req.url); | ||
const template = await server.transformIndexHtml( | ||
url.toString(), | ||
indexHtml | ||
); | ||
|
||
const head = template.match(/<head>(.+?)<\/head>/s)[1]; | ||
|
||
return render({ res, head }); | ||
}); | ||
} | ||
}; | ||
} | ||
|
||
export default defineConfig({ | ||
// @ts-ignore | ||
ssr: { | ||
noExternal: /./ | ||
}, | ||
build: { | ||
ssrManifest: true, | ||
commonjsOptions: { | ||
transformMixedEsModules: true | ||
} | ||
}, | ||
resolve: { | ||
alias: { | ||
preact: path.resolve(__dirname, './node_modules/preact'), | ||
'preact/compat': path.resolve(__dirname, './node_modules/preact/compat'), | ||
'preact/hooks': path.resolve(__dirname, './node_modules/preact/hooks') | ||
} | ||
}, | ||
plugins: [ssrPlugin(), preact()] | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.