Skip to content

Commit

Permalink
Add the ability to configure a post render script
Browse files Browse the repository at this point in the history
  • Loading branch information
alexpozzi committed Jul 19, 2021
1 parent 72e40d7 commit dc6a3e1
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 0 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
*

!src/
!scripts/
!.babelrc
!package.json
!yarn.lock
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ RUN chmod +x /usr/local/bin/dumb-init
WORKDIR /app

COPY --chown=1000:1000 src/ src/
COPY --chown=1000:1000 scripts/ scripts/
COPY --chown=1000:1000 package.json package.json
COPY --chown=1000:1000 yarn.lock yarn.lock
COPY --chown=1000:1000 .babelrc .babelrc
Expand Down
2 changes: 2 additions & 0 deletions docker-compose.test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ services:
- WORKER_ENABLED=1
- QUEUE_REDIS_DSN=redis://redis:6379
- WORKER_RENDERER_REDIRECTIONS=http://external-nginx|http://nginx
volumes:
- ./fixtures/scripts/postRender.js:/app/scripts/postRender.js:ro

redis:
image: redis:6.2.2-buster
Expand Down
10 changes: 10 additions & 0 deletions fixtures/nginx/html/post-render-script.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>A static HTML page (post render script)</title>
</head>
<body>
<h1>A static HTML page (post render script)</h1>
</body>
</html>
11 changes: 11 additions & 0 deletions fixtures/scripts/postRender.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

postRenderFunction = () => {
if ('/post-render-script.html' === window.location.pathname) {
const paragraphElement = document.createElement('p')
const textNode = document.createTextNode("This element has been created by the post render script.");

paragraphElement.appendChild(textNode)

document.body.append(paragraphElement)
}
}
23 changes: 23 additions & 0 deletions scripts/postRender.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Post render script executed by Puppeteer's evaluate method before returning
* the rendered html page. See https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pageevaluatepagefunction-args)
* for more information.
*
* In order to use a custom post render script you have to mount your own
* script as a Docker volume to `/app/scripts/postRender.js` location.
* Your custom script will just have to assign the function you want to execute
* to the `postRenderFunction` variable.
*
* Example:
* ```javascript
* // Adds the serialized Redux store
* postRenderFunction = function () {
* var preloadedState = yourReduxStore.getState();
* var script = document.createElement('script');
* script.type = 'text/javascript';
* script.text = 'window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState).replace(/</g, \\u003c')}';
*
* document.body.prepend(script);
* }
* ```
*/
20 changes: 20 additions & 0 deletions src/e2e.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,26 @@ describe('e2e :: render', () => {
`))
})

it(`asserts that a static page with post render script is rendered`, async () => {
const res = await fetch(`http://manager:8080/render?url=http://nginx/post-render-script.html`)
const content = await res.text()

expect(res.status).toBe(200)
expect(trimStringForComparison(content)).toBe(trimStringForComparison(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>A static HTML page (post render script)</title>
</head>
<body>
<h1>A static HTML page (post render script)</h1>
<p>This element has been created by the post render script.</p>
</body>
</html>
`))
})

it(`asserts that a dynamic page is rendered`, async () => {
const res = await fetch(`http://manager:8080/render?url=http://nginx/dynamic.html`)
const content = await res.text()
Expand Down
26 changes: 26 additions & 0 deletions src/worker/renderers/chrome/renderer.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
import browserRequestHandler from './browserRequestHandler'
import { formatException } from './../../../logger'
import fs from 'fs'
import getBrowserProvider from './browserProvider'
import path from 'path'
import { reduce } from 'ramda'
import vm from 'vm'

const POST_RENDER_SCRIPT_PATH = path.join(process.cwd(), 'scripts/postRender.js')

const resolvePostRenderFunction = () => {
const context = { postRenderFunction: () => {} }

const fileStats = fs.statSync(POST_RENDER_SCRIPT_PATH, { throwIfNoEntry: false })
if (fileStats && fileStats.isFile()) {
const script = new vm.Script(
fs.readFileSync(
POST_RENDER_SCRIPT_PATH,
{ encoding: 'utf8', flag: 'r' },
),
)

vm.createContext(context)
script.runInContext(context)
}

return context.postRenderFunction
}

// renderPageContent :: (Configuration, Logger, BrowserInstance, String) -> RenderedPage
const renderPageContent = async (configuration, logger, browserInstance, url) => {
Expand Down Expand Up @@ -34,6 +58,8 @@ const renderPageContent = async (configuration, logger, browserInstance, url) =>
timeout: configuration.worker.renderer.timeout,
})

await page.evaluate(resolvePostRenderFunction())

return await page.content()
}

Expand Down
2 changes: 2 additions & 0 deletions src/worker/renderers/chrome/renderer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ describe('worker :: renderer', () => {
on: jest.fn(),
goto: jest.fn(),
content: jest.fn(() => Promise.resolve('My page content')),
evaluate: jest.fn(),
}

getBrowserProvider.mockReturnValueOnce(({
Expand All @@ -58,6 +59,7 @@ describe('worker :: renderer', () => {
waitUntil: 'networkidle0',
timeout: 20000,
})
expect(pageMock.evaluate).toHaveBeenCalledTimes(1)
expect(browserCleanupMock).toHaveBeenCalledTimes(1)
})

Expand Down

0 comments on commit dc6a3e1

Please sign in to comment.