Skip to content

Instantly share code, notes, and snippets.

@activescott
Created December 14, 2019 22:29
Show Gist options
  • Save activescott/fadc5251b682f71e9b2b4d7919f5fc5d to your computer and use it in GitHub Desktop.
Save activescott/fadc5251b682f71e9b2b4d7919f5fc5d to your computer and use it in GitHub Desktop.
Example of Manual Server-Side Rendering (SSR) with React & TypeScript
// 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")
})
})
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