Rendertron is a headless Chrome rendering solution designed to render & serialise web pages on the fly.
๐จ Built with Puppeteer
Rendertron is designed to enable your Progressive Web App (PWA) to serve the correct content to any bot that doesn't render or execute JavaScript. Rendertron runs as a standalone HTTP server. Rendertron renders requested pages using Headless Chrome, auto-detecting when your PWA has completed loading and serializes the response back to the original request. To use Rendertron, your application configures middleware to determine whether to proxy a request to Rendertron. Rendertron is compatible with all client side technologies, including web components.
Demo endpoint
A demo Rendertron service is available at https://render-tron.appspot.com/. It is not designed to be used as a production endpoint. You can use it, but there are no uptime guarantees.
Once you have the service up and running, you'll need to implement the differential serving layer. This checks the user agent to determine whether prerendering is required.
This is a list of middleware available to use with the Rendertron service:
- Express.js middleware
- Firebase functions (Community maintained)
- ASP.net core middleware (Community maintained)
- Python (Django) middleware and decorator (Community maintained)
Rendertron is also compatible with prerender.io middleware. Note: the user agent lists differ there.
GET /render/<url>
The render
endpoint will render your page and serialize your page. Options are
specified as query parameters:
mobile
defaults tofalse
. Enable by passing?mobile
to request the mobile version of your site.refreshCache
: PassrefreshCache=true
to ignore potentially cached render results and treat the request as if it is not cached yet. The new render result is used to replace the previous result.
GET /screenshot/<url>
POST /screenshot/<url>
The screenshot
endpoint can be used to verify that your page is rendering
correctly.
Both endpoints support the following query parameters:
width
defaults to1000
- specifies viewport width.height
defaults to1000
- specifies viewport height.mobile
defaults tofalse
. Enable by passing?mobile
to request the mobile version of your site.
Additional options are available as a JSON string in the POST
body. See
Puppeteer documentation
for available options. You cannot specify the type
(defaults to jpeg
) and
encoding
(defaults to binary
) parameters.
GET /invalidate/<url>
The invalidate
endpoint will remove cache entried for <url>
from the configured cache (in-memory, filesystem or cloud datastore).
When setting query parameters as part of your URL, ensure they are encoded correctly. In JS,
this would be encodeURIComponent(myURLWithParams)
. For example to specify page=home
:
https://render-tron.appspot.com/render/http://my.domain/%3Fpage%3Dhome
The service detects when a page has loaded by looking at the page load event, ensuring there are no outstanding network requests and that the page has had ample time to render.
There is a hard limit of 10 seconds for rendering. Ensure you don't hit this budget by ensuring your application is rendered well before the budget expires.
Headless Chrome supports web components but shadow DOM is difficult to serialize effectively. As such, shady DOM (a lightweight shim for Shadow DOM) is required for web components.
If you are using web components v0 (deprecated), you will need to enable Shady DOM to
render correctly. In Polymer 1.x, which uses web components v0, Shady DOM is enabled by default.
If you are using Shadow DOM, override this by setting the query parameter dom=shady
when
directing requests to the Rendertron service.
If you are using web components v1 and either webcomponents-lite.js
or webcomponents-loader.js
,
set the query parameter wc-inject-shadydom=true
when directing requests to the Rendertron
service. This renderer service will force the necessary polyfills to be loaded and enabled.
Status codes from the initial requested URL are preserved. If this is a 200, or 304, you can set the HTTP status returned by the rendering service by adding a meta tag.
<meta name="render:status_code" content="404" />
To install Rendertron and run it locally, first install Rendertron:
npm install -g rendertron
With Chrome installed on your machine run the Rendertron CLI:
rendertron
Clone and install dependencies:
git clone https://github.com/GoogleChrome/rendertron.git
cd rendertron
npm install
npm run build
With a local instance of Chrome installed, you can start the server locally:
npm run start
gcloud app deploy app.yaml --project <your-project-id>
Rendertron no longer includes a Docker file. Instead, refer to Puppeteer documentation on how to deploy run headless Chrome in Docker.
When deploying the service, set configuration variables by including a config.json
in the
root. Available configuration options:
timeout
default10000
- set the timeout used to render the target page.port
default3000
- set the port to use for running and listening the rendertron service. Note if process.env.PORT is set, it will be used instead.host
default0.0.0.0
- set the hostname to use for running and listening the rendertron service. Note if process.env.HOST is set, it will be used instead.width
default1000
- set the width (resolution) to be used for rendering the page.height
default1000
- set the height (resolution) to be used for rendering the page.cache
defaultnull
- set todatastore
to enable caching on Google Cloud using datastore only use if deploying to google cloud,memory
to enable in-memory caching orfilesystem
to enable disk based cachingcacheConfig
- an object array to specify caching options
cacheDurationMinutes
default1440
- set an expiry time in minues, defaults to 24 hours. Set to -1 to disable cache ExpirationcacheMaxEntries
default100
- set the maximum number of entries stored in the selected cache method. Set to-1
to allow unlimited caching. If using the datastore caching method, setting this value over1000
may lead to degraded performance as the query to determine the size of the cache may be too slow. If you want to allow a larger cache indatastore
consider setting this to-1
and managing the the size of your datastore using a method like this Deleting Entries in BulksnapshotDir
default<your os's default tmp dir>/renderton
- filesystem only the directory the rendertron cache files will be stored in
An example config file specifying a memory cache, with a 2 hour expiration, and a maximum of 50 entries
{
"cache": "memory",
"cacheConfig": {
"cacheDurationMinutes": 120,
"cacheMaxEntries": 50
}
}
If you're having troubles with getting Headless Chrome to run in your environment, refer to the troubleshooting guide for Puppeteer.