Skip to content

Commit

Permalink
Merge pull request #30 from sevenwestmedia/feature/add-prebody-pagetag
Browse files Browse the repository at this point in the history
Adds prebody page tag to insert content before root element
  • Loading branch information
antonjb authored Dec 6, 2019
2 parents d4f753f + 8015c08 commit 03b6a00
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 21 deletions.
1 change: 1 addition & 0 deletions lib/runtime/server/middleware/default-html-middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export const getDefaultHtmlMiddleware = (log: Logger, runtimeConfig: RuntimeConf
head: undefined,
pageTags: {
body: getBodyAssets(buildAssets),
preBody: [],
head: getHeadAssets(buildAssets),
},
renderResult: '',
Expand Down
27 changes: 12 additions & 15 deletions lib/runtime/server/ssr/create-middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,11 @@ export interface RenderContext<SSRRequestProps = object> {
promiseTracker: PromiseTracker
}

export type RenderApp<SSRRequestProps extends object> = (
params: {
log: Logger
context: RenderContext<SSRRequestProps>
req: Request
},
) => JSX.Element
export type RenderApp<SSRRequestProps extends object> = (params: {
log: Logger
context: RenderContext<SSRRequestProps>
req: Request
}) => JSX.Element

export interface RenderHtmlParams<SSRRequestProps extends object, RenderResult> {
head: HelmetData | undefined
Expand All @@ -47,14 +45,12 @@ export type RenderHtml<SSRRequestProps extends object, RenderResult> = (
params: RenderHtmlParams<SSRRequestProps, RenderResult>,
) => string

export type CreatePageTags<SSRRequestProps> = (
options: {
buildAssets: Assets
helmetTags: string[]
stateTransfers: PageTag[]
renderContext: RenderContext<SSRRequestProps>
},
) => PageTags
export type CreatePageTags<SSRRequestProps> = (options: {
buildAssets: Assets
helmetTags: string[]
stateTransfers: PageTag[]
renderContext: RenderContext<SSRRequestProps>
}) => PageTags

export interface ServerSideRenderMiddlewareOptions<SSRRequestProps extends object, RenderResult> {
app: Express & { log: Logger }
Expand Down Expand Up @@ -157,6 +153,7 @@ export const createSsrMiddleware = <SSRRequestProps extends object, RenderResult
? options.createPageTags({ buildAssets, helmetTags, stateTransfers, renderContext })
: {
body: [...getBodyAssets(buildAssets)],
preBody: [],
head: [
...helmetTags.map(tag => ({ tag })),
...getHeadAssets(buildAssets),
Expand Down
1 change: 1 addition & 0 deletions lib/runtime/server/ssr/full-render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export interface PageTag {

export interface PageTags {
head: PageTag[]
preBody: PageTag[]
body: PageTag[]
}

Expand Down
10 changes: 6 additions & 4 deletions lib/runtime/server/ssr/helpers/render-html.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { RenderHtml } from '../create-middleware'
import { PageTag } from '../full-render'

const returnTag = (pageTag: PageTag) => pageTag.tag

export const renderHtml: RenderHtml<any, string> = ({ pageTags, renderResult }) => {
return `<!DOCTYPE html>
Expand All @@ -7,13 +10,12 @@ export const renderHtml: RenderHtml<any, string> = ({ pageTags, renderResult })
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
${pageTags.head.map(headAsset => headAsset.tag).join(`
`)}
${pageTags.head.map(returnTag).join(``)}
</head>
<body>
${pageTags.preBody.map(returnTag).join(``)}
<div id="root">${renderResult}</div>
${pageTags.body.map(bodyAsset => bodyAsset.tag).join(`
`)}
${pageTags.body.map(returnTag).join(``)}
</body>
</html>`
}
44 changes: 42 additions & 2 deletions test/runtime/server/ssr.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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(`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="test" />
</head>
<body>
<div>prebody</div>
<div id="root"><div></div></div>
<div>body</div>
</body>
</html>`)
})
},
{
createPageTags: () => ({
body: [{ tag: '<div>body</div>' }],
head: [{ tag: '<link rel="test" />' }],
preBody: [{ tag: '<div>prebody</div>' }],
}),
},
),
)

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface SSRState {}
export interface Fixture {
Expand All @@ -304,7 +338,12 @@ export interface Fixture {

function ssrFixture(
test: (fixture: Fixture) => Promise<any>,
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 () => {
Expand All @@ -326,6 +365,7 @@ function ssrFixture(
renderHtml,
setupRequest: async () => ({}),
ssrTimeoutMs: 1000,
createPageTags: options.createPageTags,
})

app.get('*', ssrMiddleware)
Expand Down

0 comments on commit 03b6a00

Please sign in to comment.