From 8015c084b78ca097f06e27c68606ae2dd4d67e0a Mon Sep 17 00:00:00 2001 From: Anton Ball Date: Fri, 6 Dec 2019 11:55:27 +0800 Subject: [PATCH] Adds prebody page tag to insert content before root element We have run into the need to be able to insert content before the root element or another way of thinking about it, as the first element in the body. This new prop is called preBody and is by default empty but you can add html content as needed. Tests have been added in ssr.test.tsx to test all of the page tags. --- .../middleware/default-html-middleware.ts | 1 + lib/runtime/server/ssr/create-middleware.ts | 27 +++++------- lib/runtime/server/ssr/full-render.tsx | 1 + lib/runtime/server/ssr/helpers/render-html.ts | 10 +++-- test/runtime/server/ssr.test.tsx | 44 ++++++++++++++++++- 5 files changed, 62 insertions(+), 21 deletions(-) diff --git a/lib/runtime/server/middleware/default-html-middleware.ts b/lib/runtime/server/middleware/default-html-middleware.ts index 9644005e..e9010f9d 100644 --- a/lib/runtime/server/middleware/default-html-middleware.ts +++ b/lib/runtime/server/middleware/default-html-middleware.ts @@ -78,6 +78,7 @@ export const getDefaultHtmlMiddleware = (log: Logger, runtimeConfig: RuntimeConf head: undefined, pageTags: { body: getBodyAssets(buildAssets), + preBody: [], head: getHeadAssets(buildAssets), }, renderResult: '', diff --git a/lib/runtime/server/ssr/create-middleware.ts b/lib/runtime/server/ssr/create-middleware.ts index 6bc3cd6c..dce7160a 100644 --- a/lib/runtime/server/ssr/create-middleware.ts +++ b/lib/runtime/server/ssr/create-middleware.ts @@ -28,13 +28,11 @@ export interface RenderContext { promiseTracker: PromiseTracker } -export type RenderApp = ( - params: { - log: Logger - context: RenderContext - req: Request - }, -) => JSX.Element +export type RenderApp = (params: { + log: Logger + context: RenderContext + req: Request +}) => JSX.Element export interface RenderHtmlParams { head: HelmetData | undefined @@ -47,14 +45,12 @@ export type RenderHtml = ( params: RenderHtmlParams, ) => string -export type CreatePageTags = ( - options: { - buildAssets: Assets - helmetTags: string[] - stateTransfers: PageTag[] - renderContext: RenderContext - }, -) => PageTags +export type CreatePageTags = (options: { + buildAssets: Assets + helmetTags: string[] + stateTransfers: PageTag[] + renderContext: RenderContext +}) => PageTags export interface ServerSideRenderMiddlewareOptions { app: Express & { log: Logger } @@ -157,6 +153,7 @@ export const createSsrMiddleware = ({ tag })), ...getHeadAssets(buildAssets), diff --git a/lib/runtime/server/ssr/full-render.tsx b/lib/runtime/server/ssr/full-render.tsx index 647bc990..173464a3 100644 --- a/lib/runtime/server/ssr/full-render.tsx +++ b/lib/runtime/server/ssr/full-render.tsx @@ -31,6 +31,7 @@ export interface PageTag { export interface PageTags { head: PageTag[] + preBody: PageTag[] body: PageTag[] } diff --git a/lib/runtime/server/ssr/helpers/render-html.ts b/lib/runtime/server/ssr/helpers/render-html.ts index 02c5887d..f786d5a3 100644 --- a/lib/runtime/server/ssr/helpers/render-html.ts +++ b/lib/runtime/server/ssr/helpers/render-html.ts @@ -1,4 +1,7 @@ import { RenderHtml } from '../create-middleware' +import { PageTag } from '../full-render' + +const returnTag = (pageTag: PageTag) => pageTag.tag export const renderHtml: RenderHtml = ({ pageTags, renderResult }) => { return ` @@ -7,13 +10,12 @@ export const renderHtml: RenderHtml = ({ pageTags, renderResult }) - ${pageTags.head.map(headAsset => headAsset.tag).join(` - `)} + ${pageTags.head.map(returnTag).join(``)} + ${pageTags.preBody.map(returnTag).join(``)}
${renderResult}
- ${pageTags.body.map(bodyAsset => bodyAsset.tag).join(` - `)} + ${pageTags.body.map(returnTag).join(``)} ` } diff --git a/test/runtime/server/ssr.test.tsx b/test/runtime/server/ssr.test.tsx index be144ecc..c5163de4 100644 --- a/test/runtime/server/ssr.test.tsx +++ b/test/runtime/server/ssr.test.tsx @@ -4,7 +4,7 @@ import { Route } from 'react-router-dom' import supertest from 'supertest' import { consoleLogger, Logger, noopLogger } from 'typescript-log' import { createServer } from '../../../lib/runtime/server/server' -import { createSsrMiddleware, RenderApp } from '../../../lib/runtime/server/ssr' +import { createSsrMiddleware, RenderApp, CreatePageTags } from '../../../lib/runtime/server/ssr' import { Status404Error } from '../../../lib/runtime/server/ssr/errors' import { renderHtml } from '../../../lib/runtime/server/ssr/helpers/render-html' import { PromiseCompletionSource, PromiseTracker } from '../../../lib/runtime/universal' @@ -295,6 +295,40 @@ it( ), ) +it( + 'renders the custom tags that are passed', + ssrFixture( + fixture => { + return fixture.server + .get('/') + .expect(200) + .then(res => { + expect(res.text).toEqual(` + + + + + + + + +
prebody
+
+
body
+ +`) + }) + }, + { + createPageTags: () => ({ + body: [{ tag: '
body
' }], + head: [{ tag: '' }], + preBody: [{ tag: '
prebody
' }], + }), + }, + ), +) + // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface SSRState {} export interface Fixture { @@ -304,7 +338,12 @@ export interface Fixture { function ssrFixture( test: (fixture: Fixture) => Promise, - options: { errorLocation?: string; pageNotFoundLocation?: string; log?: Logger } = {}, + options: { + errorLocation?: string + pageNotFoundLocation?: string + log?: Logger + createPageTags?: CreatePageTags<{}> + } = {}, ) { // Return the test for Jest to run return async () => { @@ -326,6 +365,7 @@ function ssrFixture( renderHtml, setupRequest: async () => ({}), ssrTimeoutMs: 1000, + createPageTags: options.createPageTags, }) app.get('*', ssrMiddleware)