server/html.ts (41 lines of code) (raw):
import { createHash } from 'crypto';
import type { Globals } from '../shared/globals';
interface HtmlAndScriptHashes {
body: string;
hashes: string[];
}
declare let WEBPACK_BUILD: string;
/**
* https://medium.com/styled-components/the-simple-guide-to-server-side-rendering-react-with-styled-components-d31c6b2b8fbf
* Html
* This Html.js file acts as a template that we insert all our generated
* application code into before sending it to the client as regular HTML.
* Note we're returning a template string from this function.
*/
const insertGlobals = (globals: Globals) => {
return `window.guardian = ${JSON.stringify(globals)}`;
};
const htmlAndScriptHashes: (_: {
readonly title: string;
readonly src: string;
readonly globals: Globals;
}) => HtmlAndScriptHashes = ({ title, src, globals }) => {
const mainScriptBundleSrc = `var s = document.createElement("script"); s.src = "${src}?release=${WEBPACK_BUILD}";document.body.appendChild(s);`;
const setGuardianWindowSrc = insertGlobals(globals);
return {
body: `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>${title}</title>
<script>${setGuardianWindowSrc}</script>
<link rel="shortcut icon" type="image/png" href="https://assets.guim.co.uk/images/favicons/46bd2faa1ab438684a6d4528a655a8bd/32x32.ico" />
</head>
<body style="margin:0">
<div id="app"></div>
</body>
<script>${mainScriptBundleSrc}</script>
</html>
`,
hashes: [
createHash('sha256').update(mainScriptBundleSrc).digest('base64'),
createHash('sha256').update(setGuardianWindowSrc).digest('base64'),
],
};
};
export { htmlAndScriptHashes };