import * as React from 'react' import * as fs from 'fs' import * as cheerio from 'cheerio' import * as types from 'src/types' import { IncomingMessage, ServerResponse } from 'http' import { getConfig } from 'config/config' import { findMatchedRoute, callGetInitialProps } from 'src/utils' import ReactDOMServer from 'react-dom/server' import Root from 'src/Root' import DefaultApp from 'src/App' const config = getConfig() const htmlPath = config.isDev ? config.htmlTemplatePath : config.builtHTMLPath const template = fs.readFileSync(htmlPath, 'utf8') function writeDataToHTML($: CheerioStatic, pageProps: object) { const data = JSON.stringify({ pageProps, }) const scripts = $('script') if (scripts.length) { $(scripts.get(0)).before(` ` ) } else { $('body').append( `` ) } } function appendScriptOnDevelop($: CheerioStatic) { if (config.isDev) { const scriptUrl = config.publicPath + 'app.js' $('body').append(` `) } } export async function renderToString( req: IncomingMessage, res: ServerResponse, url: string, options: types.RenderOptions, ): Promise { const $ = cheerio.load(template, { decodeEntities: config.decodeEntities, }) const matched = findMatchedRoute(url, options.routes) const App = options.App || DefaultApp const initialProps = await callGetInitialProps( App, matched ? matched.component : null, url, req, res, ) const content = ReactDOMServer.renderToString( ) $(options.container).html(content) appendScriptOnDevelop($) writeDataToHTML($, initialProps) return $.html() }