Skip to content
A server side render service based on puppeteer
JavaScript Vue PHP Dockerfile CSS Shell HTML
Branch: master
Clone or download
Latest commit 6e4cf71 Feb 11, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
Client docs: update Jan 26, 2019
DemoPage chore: fix github security alert for bootstrap Jan 20, 2019
Meta chore: update Jan 20, 2019
Server docs: update Jan 26, 2019
.gitignore keep server cache folder Aug 15, 2018
Dockerfile feat: add docker version Feb 11, 2019 add LICENSE, update documentation Aug 13, 2018 fix: fix typo Feb 11, 2019

Ciao SSR

A server side render service based on puppeteer

This is a puppeteer(chrome headless) server side render service.


  • Can limit render origin
  • Cache


  • Node.js 8.x up


How server side render work?

Before use this service, you must know how server side render work.

Step Role File path Do
1 Proxy(.htaccess) dist/.htaccess Detect origin is crawler or not by checking user agent.
2 Middleware(ssr.php) dist/ssr.php Send the request with page's url to this service's http server.
3 Puppeteer If origin is valid, it will trigger server side render crawler(puppeteer) start.
4 Response The http server of this service will return response with render result.
5 Middleware(ssr.php) dist/ssr.php Render the result to crawler.

Icon Credit

Install Google Chrome

Skip this step if you has install chrome browser

curl -sL | bash

Setup/Start server


yarn global add ciao-ssr

Start server

ciao-ssr --config=/file-to-your/config.json

Clean cache

ciao-ssr --clean


config json


  "allowOrigin": [
    "http://localhost:8081", ""
  "cache": {
    "ttl": 60,
    "maxsize": 1000
  "debug": true
  • port(optional): Number, port of Node.js express app, default is 3000.
  • host(optional): String, host of Node.js express app, default is 'localhost'.
  • allowOrigin(required): String/Array, allow origin, you can set it as * if you don't want to limit any origin.
  • timeout(optional): Number, if client don't trigger server side render service in this timeout, crawler will auto get page result and response, default is 5000ms, at most 15000ms.
  • cache(optional): Object, configure cache feature.
    • ttl(optional): Number, time to life of cache(minutes), default is 1 minute.
    • maxsize(optional): Number, maxsize of cache file on disk(Kilobyte), default is 1MB.
    • path(optional): String, cache file store path, default is 'cache'.
  • debug(optional): Boolean, debug mode, it will open chrome without headless mode.
  • launchOptions(optional): Object, you can setup any custom puppeteer launch option by this property

Client side(web)


yarn add ciao-ssr-client

Copy proxy(.htaccess) and middleware(ssr.php) to web root

You can find them in node_modules/ciao-ssr-client

Or copy here


<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /

  RewriteCond %{HTTP_USER_AGENT} !(firefox|chrome|safari|msie|edge|opera) [NC]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^(.*)$ ssr.php [L]

  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]



$ssrHost = 'https://ssr.server';
$user_agent = urlencode($_SERVER['HTTP_USER_AGENT']);
$port = '';

if($_SERVER["REQUEST_SCHEME"] == 'http' && $_SERVER["SERVER_PORT"] != 80){
    $port = ':'.$_SERVER["SERVER_PORT"];

if($_SERVER["REQUEST_SCHEME"] == 'https' && $_SERVER["SERVER_PORT"] != 443){
    $port = ':'.$_SERVER["SERVER_PORT"];
$requestUrl = $host.$port.$_SERVER['REQUEST_URI'];
$result = json_decode(file_get_contents($ssrHost.'/render?url='.$requestUrl), true);

if(!$result || !$result['statusCode']) {
    header("HTTP/1.0 404 Not Found");

echo $result['content'];

Use client library in web

We provide a client side library to trigger server side render service

import ServerSideRenderClient from 'ciao-ssr-client'

// when your all async data are ready and render

// when your page is in error type

// when you want to custom error status code in error page

Apache configuration

Enable apache rewrite/proxy/proxy_http modules

sudo a2enmod rewrite
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo service apache2 restart

Setup domain

<VirtualHost *:80>
    ProxyRequests Off
    ProxyPreserveHost On
    ProxyVia Full
    <Proxy *>
        Require all granted
    <Location />
        ProxyPass http://localhost:3000/

Enable domain and restart apache

sudo a2ensite
sudo service apache2 restart

Manage service with PM2

PM2 is an advanced Node.js process manager.

You can manage server side render service easily by using PM2.


sudo yarn global add pm2


# start service
pm2 start ciao-ssr --name="ssr" -- --config=/file-to-your/config.json

# stop service
pm2 stop ssr

# delete service
pm2 delete ssr

# show status
pm2 status ssr

# show log
pm2 log ssr

Start With Docker

This service will be started by pm2 when your container start

Just setup port and config json file of your local host

docker run --name ssr -p 3000:3000 -v /path-to-your-config.json:/config/ssr.json -d ciaochung/ciao-ssr


  • port: 3000
  • config json file path: /home/user/config/ssr.json
docker run --name ssr -p 3000:3000 -v /home/user/config/ssr.json:/config/ssr.json -d ciaochung/ciao-ssr
You can’t perform that action at this time.