Created
February 28, 2019 01:29
-
-
Save ninetails/414e63f3207f4f6b18bc93e885c9a869 to your computer and use it in GitHub Desktop.
reset
This file contains hidden or 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
import React, { Fragment, Suspense } from 'react' | |
import Head from '@ninetails-monorepo-react-ssr/react-kabocha' | |
import { Link, Route, Switch } from 'react-router-dom' | |
const UniversalSuspense = global.window ? Suspense : Fragment | |
const test = { | |
read (timeout, cache = global.window) { | |
if (this.value) { | |
if (cache) { | |
return this.value | |
} | |
const output = this.value | |
delete this.value | |
delete this.promise | |
return output | |
} | |
if (this.promise) { | |
throw this.promise | |
} | |
this.promise = new Promise(resolve => { | |
console.log('settimeout start', Date.now() / 1000) | |
setTimeout(() => { | |
console.log('settimeout end', Date.now() / 1000) | |
this.value = 'foo' | |
resolve(this.value) | |
}, timeout) | |
}) | |
throw this.promise | |
} | |
} | |
function LazyTest () { | |
const testValue = test.read(2000) | |
return <div>{testValue}</div> | |
} | |
function Home () { | |
return ( | |
<div> | |
<Head> | |
<title>Home</title> | |
</Head> | |
Home | |
</div> | |
) | |
} | |
function About () { | |
return ( | |
<div> | |
<Head> | |
<title>About</title> | |
</Head> | |
About | |
<UniversalSuspense maxDuration={500} fallback={<div>loading...</div>}> | |
<LazyTest /> | |
</UniversalSuspense> | |
</div> | |
) | |
} | |
const App = () => ( | |
<div> | |
<Head> | |
<meta charSet='utf-8' /> | |
<meta name='viewport' content='width=device-width, initial-scale=1' /> | |
</Head> | |
<nav> | |
<ul> | |
<li> | |
<Link to='/'>Home</Link> | |
</li> | |
<li> | |
<Link to='/about'>About</Link> | |
</li> | |
</ul> | |
</nav> | |
<Switch> | |
<Route exact path='/' component={Home} /> | |
<Route path='/about' component={About} /> | |
</Switch> | |
</div> | |
) | |
export default App |
This file contains hidden or 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
import React from 'react' | |
import ReactDOM from 'react-dom' | |
import { HeadProvider } from '@ninetails-monorepo-react-ssr/react-kabocha' | |
import { BrowserRouter as Router } from 'react-router-dom' | |
import getRoot from './client/getRoot' | |
import App from './App' | |
const root = getRoot(process.env.REACT_APP_ROOT) | |
ReactDOM.createRoot(root, { hydrate: root.hasChildNodes() }).render( | |
<HeadProvider> | |
<Router> | |
<App /> | |
</Router> | |
</HeadProvider> | |
) |
This file contains hidden or 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
import React from 'react' | |
import { renderToStaticNodeStream, renderToString } from 'react-dom/server' | |
import { | |
HeadProvider, | |
createRegistry | |
} from '@ninetails-monorepo-react-ssr/react-kabocha' | |
import { StaticRouter as Router } from 'react-router-dom' | |
import App from './App' | |
async function renderContent (props) { | |
try { | |
return renderToString( | |
<HeadProvider registry={props.registry}> | |
<Router location={props.location} context={props.context}> | |
<App /> | |
</Router> | |
</HeadProvider> | |
) | |
} catch (err) { | |
if (err instanceof Promise) { | |
await err | |
return renderContent(props) | |
} | |
throw err | |
} | |
} | |
function serverRenderer ({ clientStats, serverStats }) { | |
const { main } = clientStats.assetsByChunkName | |
const mainSrc = typeof main === 'string' ? main : main[0] | |
return async (req, res, next) => { | |
const registry = createRegistry() | |
const context = {} | |
try { | |
const content = await renderContent({ | |
context, | |
location: req.url, | |
registry | |
}) | |
if (context.url) { | |
return res.redirect(301, context.url) | |
} | |
res.status(200).write('<!doctype html>') | |
renderToStaticNodeStream( | |
<html> | |
<head>{registry.head()}</head> | |
<body> | |
<div | |
id={process.env.REACT_APP_ROOT || 'root'} | |
dangerouslySetInnerHTML={{ __html: content }} | |
/> | |
<script src={`/${mainSrc}`} /> | |
</body> | |
</html> | |
).pipe( | |
res, | |
{ end: 'false' } | |
) | |
} catch (err) { | |
// @todo error page | |
console.error(err) | |
res.status(500).send('Server error') | |
} | |
} | |
} | |
export default serverRenderer |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment