Created
December 14, 2019 22:29
-
-
Save activescott/fadc5251b682f71e9b2b4d7919f5fc5d to your computer and use it in GitHub Desktop.
Example of Manual Server-Side Rendering (SSR) with React & TypeScript
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 doesn't go through babel or webpack transformation. | |
// Make sure the syntax and sources this file requires are compatible with the current node version you are running | |
// See https://github.com/zeit/next.js/issues/1245 for discussions on Universal Webpack or universal Babel | |
import { createServer } from "http" | |
import { parse } from "url" | |
import next from "next" | |
import render from "./lib/ssr" | |
const dev = process.env.NODE_ENV !== "production" | |
const app = next({ dev }) | |
const handle = app.getRequestHandler() | |
app.prepare().then(() => { | |
createServer((req, res) => { | |
// Be sure to pass `true` as the second argument to `url.parse`. | |
// This tells it to parse the query portion of the URL. | |
const parsedUrl = parse(req.url, true) | |
const { pathname, query } = parsedUrl | |
console.log("server path/query:", { pathname, query }) | |
if (pathname === "/test-ssr") { | |
render(req, res, pathname, query) | |
} else { | |
handle(req, res, parsedUrl) | |
} | |
}).listen(3000, () => { | |
//if (err) throw err | |
console.log("> Ready on http://localhost:3000") | |
}) | |
}) |
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
import React from "react" | |
import ReactDOMServer from 'react-dom/server' | |
import { ServerResponse, IncomingMessage } from 'http' | |
import { ParsedUrlQuery } from 'querystring' | |
import ProductList, { getProductsApiUrl, WatchProduct } from '../components/catalog/ProductList' | |
import { BackendApi } from './BackendApi' | |
import { urlFromInitialProps } from './nextUtil' | |
// See server.ts for how to call this | |
const render = async (req: IncomingMessage, res: ServerResponse, pathname: string, query: ParsedUrlQuery): Promise<void> => { | |
const baseUrl = urlFromInitialProps(req) | |
const page = 1 | |
const pageSize = 20 | |
const apiPath = getProductsApiUrl(page, pageSize) | |
const resp = await new BackendApi().get<{ data: WatchProduct[] }>( | |
baseUrl + apiPath | |
) | |
const props = { | |
data: { | |
products: resp.data, | |
page, | |
pageSize | |
} | |
} | |
res.setHeader("content-type", "text/html; charset=utf-8") | |
/* pipes for efficiency: | |
const htmlStream = ReactDOMServer.renderToNodeStream((<ProductList data={props.data} />)) | |
htmlStream.pipe(res) | |
*/ | |
const htmlStr = ReactDOMServer.renderToString((<ProductList data={props.data} />)) | |
console.log({ htmlStr }) | |
res.write(htmlStr) | |
} | |
export default render |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment