Deploying to Render
Relevant source files
The following files were used as context for generating this wiki page:
Rendertron is a standalone headless Chrome rendering solution, built with Puppeteer, designed to be deployed as an HTTP server. Its primary purpose is to render and serialize web pages on the fly, enabling Progressive Web Apps (PWAs) and other JavaScript-heavy sites to serve fully-rendered HTML to bots and crawlers that do not execute JavaScript, thereby improving SEO. The service is built as a Koa.js application and is suitable for deployment on platforms like Render.
The system works by exposing simple API endpoints to render a URL or take a screenshot. A client application, such as an Express.js app, uses a specific middleware to inspect the user agent of an incoming request. If the user agent matches a known bot, the request is proxied to the deployed Rendertron service. Rendertron then uses a headless Chrome instance to load the page, waits for it to be idle, and returns the serialized HTML content.
Sources: README.md:10-16, src/rendertron.ts:13-15, CHANGELOG.md:12-13
System Architecture
The Rendertron service is a Node.js application built with TypeScript. It uses a Koa.js server to handle HTTP requests and Puppeteer to control a headless Chrome browser for rendering. An optional caching layer using Google Cloud Datastore can be enabled to improve performance for repeated requests.
Sources: package.json:2-4,18,34, src/rendertron.ts:1-11, 44-47
High-Level Component Diagram
This diagram illustrates the main components of the Rendertron service.
This flow shows a request being intercepted by middleware. If it's from a bot, it's sent to the Rendertron Koa Server, which uses the Renderer and Puppeteer to get the page content, and returns it.
Sources: README.md:14-16, middleware/README.md:9-11, src/rendertron.ts:44-47
Core Components
Rendertron Server (rendertron.ts)
The entry point of the service is the Rendertron class. Its initialize method sets up the Koa application, launches a Puppeteer-managed browser instance, and starts listening for requests.
The server configuration includes:
- Middleware:
koa-logger,koa-compressfor compression, andkoa-bodyparserfor parsing POST bodies. - Health Check: An
/_ah/healthendpoint that responds with 'OK', common for cloud environment health checks. - API Routes: Defines routes for
/renderand/screenshotendpoints. - Caching: Optionally initializes and uses a
DatastoreCachemiddleware ifdatastoreCacheis enabled in the configuration.
Sources: src/rendertron.ts:18-54
Server Initialization Flow
This diagram shows the sequence of operations when the Rendertron service starts.
Sources: src/rendertron.ts:21-54
Renderer (renderer.ts)
The Renderer class encapsulates the core logic of interacting with the headless Chrome browser via Puppeteer. It is responsible for both serializing page content and taking screenshots.
Key steps in the rendering process (serialize method):
- A new browser page is created.
- The viewport is set, and a mobile user agent is applied if requested.
- Polyfills for Web Components (
ShadyDOM,ShadyCSS) are forced to ensure compatibility. - The page navigates to the target URL, waiting until network activity is idle (
networkidle0). - After the page loads, it executes a client-side script to strip out
<script>and<link rel="import">tags to prevent further execution. JSON-LD scripts (application/ld+json) are preserved for structured data. - A
<base>tag is injected to ensure relative URLs resolve correctly. - The final, serialized
outerHTMLof the document element is returned.
Sources: src/renderer.ts:16-22, 24-132, src/test/app-test.ts:77-83
API Endpoints
The service exposes two main endpoints for rendering and screenshotting, along with a health check.
| Method | Endpoint | Description |
|---|---|---|
GET | /_ah/health | A health check endpoint that returns a 200 status with "OK" body. |
GET | /render/<url> | Renders the given URL and returns the serialized HTML content. |
GET/POST | /screenshot/<url> | Captures a screenshot of the given URL and returns a JPEG image. |
Sources: src/rendertron.ts:40-42, 49-54, README.md:36-57
/render/<url>
This endpoint renders a page and returns its serialized HTML. The URL to be rendered must be properly encoded.
Query Parameters:
| Parameter | Description | Default |
|---|---|---|
mobile | If present, renders the page with a mobile user agent and viewport. | false |
wc-inject-shadydom | Forces Web Components polyfills to be loaded. | false |
Status Code Handling:
Rendertron preserves the status code from the initial request to the target URL. However, this can be overridden by including a meta tag in the page's HTML. The service looks for the first matching tag.
<meta name="render:status_code" content="404" />
If the original status code is 304, it is treated as a 200. Non-200 status codes from the origin server are always preserved and cannot be overridden by the meta tag.
Sources: README.md:78-81, 98-101, src/rendertron.ts:80-82, src/renderer.ts:103-122, test-resources/http-meta-status-code.html:12, test-resources/http-meta-status-code-multiple.html:12-13
/screenshot/<url>
This endpoint generates a screenshot of a web page.
Query Parameters:
| Parameter | Description | Default (from config) |
|---|---|---|
width | Viewport width in pixels. | 1000 |
height | Viewport height in pixels. | 1000 |
mobile | If present, uses a mobile user agent and viewport. | false |
Additional screenshot options from the Puppeteer documentation can be passed in the body of a POST request as a JSON object.
Sources: README.md:49-65, src/rendertron.ts:98-102
Configuration
The service can be configured via a config.json file in the project root.
| Property | Type | Default | Description |
|---|---|---|---|
datastoreCache | boolean | false | Set to true to enable caching with Google Cloud Datastore. |
timeout | number | 10000 | Timeout in milliseconds for rendering a page. |
port | number | 3000 | Port for the service to listen on. Overridden by process.env.PORT. |
width | number | 1000 | Default viewport width for rendering and screenshots. |
height | number | 1000 | Default viewport height for rendering and screenshots. |
Sources: README.md:126-133, src/rendertron.ts:24, 26
Usage with Middleware
While Rendertron is a standalone service, it is designed to be used with middleware in a client application (e.g., an Express server). The middleware is responsible for deciding when to proxy a request to Rendertron.
Request Flow with Middleware
This diagram shows how a request from a bot is handled by an application using rendertron-middleware.
The middleware identifies the bot, forwards the request to the Rendertron service, and pipes the resulting serialized HTML back to the bot.
Sources: middleware/README.md:9-11, 20-25, middleware/src/middleware.ts:51-53, 90-104
Conclusion
Deploying Rendertron involves running the packaged Koa.js server, which is optimized for cloud environments like Render. It provides a robust solution for server-side rendering of modern web applications by exposing a simple yet powerful API. By integrating it with a middleware layer, applications can seamlessly serve pre-rendered content to search engines and social media crawlers, ensuring proper indexing and link previews without altering the experience for regular users.