{"id":17671886,"url":"https://github.com/ciao-chung/ciao-ssr","last_synced_at":"2025-05-07T14:21:59.340Z","repository":{"id":32862095,"uuid":"128336297","full_name":"ciao-chung/ciao-ssr","owner":"ciao-chung","description":"A server side render service based on puppeteer","archived":false,"fork":false,"pushed_at":"2022-12-10T01:35:57.000Z","size":2038,"stargazers_count":13,"open_issues_count":18,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-07T14:21:43.837Z","etag":null,"topics":["chrome-headless","puppeteer","server-side-render"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ciao-chung.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-06T04:54:06.000Z","updated_at":"2022-10-21T20:31:12.000Z","dependencies_parsed_at":"2023-01-14T22:31:09.272Z","dependency_job_id":null,"html_url":"https://github.com/ciao-chung/ciao-ssr","commit_stats":null,"previous_names":["ciao-chung/puppeteer-server-side-render"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ciao-chung%2Fciao-ssr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ciao-chung%2Fciao-ssr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ciao-chung%2Fciao-ssr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ciao-chung%2Fciao-ssr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ciao-chung","download_url":"https://codeload.github.com/ciao-chung/ciao-ssr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252892678,"owners_count":21820687,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chrome-headless","puppeteer","server-side-render"],"created_at":"2024-10-24T04:05:57.623Z","updated_at":"2025-05-07T14:21:59.299Z","avatar_url":"https://github.com/ciao-chung.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ciao SSR\n\n\u003e A server side render service based on puppeteer\n\nThis is a puppeteer(chrome headless) server side render service.\n\n## Feature\n\n* Can limit render origin\n* Cache\n\n## Required\n\n- Node.js 8.x up\n\n## Dependencies\n\n* [express](https://github.com/expressjs/express)\n* [cache-manager](https://github.com/BryanDonovan/node-cache-manager)\n* [puppeteer](https://github.com/GoogleChrome/puppeteer)\n\n## How server side render work?\n\nBefore use this service, you must know how server side render work.\n\n\u003cimg src=\"https://goo.gl/ioZGex\" style=\"width: 800px; height: 600px; max-width: 100%\"\u003e\n\nStep | Role | File path| Do\n-----|-----|-----|-----\n1 | Proxy(.htaccess) | dist/.htaccess | Detect origin is crawler or not by checking user agent. \n2 | Middleware(ssr.php) | dist/ssr.php | Send the request with page's url to this service's http server.\n3 | Puppeteer | :x: | If origin is valid, it will trigger server side render crawler(puppeteer) start.\n4 | Response | :x: | The http server of this service will return response with render result.\n5 | Middleware(ssr.php) | dist/ssr.php | Render the result to crawler.\n\n\n**Icon Credit**\n\n- **Person** icon made by [Vectors Market](https://www.flaticon.com/authors/vectors-market) from [www.flaticon.com](https://www.flaticon.com)\n- **SPA** icon made by [Smashicons](https://smashicons.com) from [www.flaticon.com](https://www.flaticon.com)\n- **Middleware** icon made by [Freepik](http://www.freepik.com) from [www.flaticon.com](https://www.flaticon.com)\n- **Crawler** icon made by [Freepik](http://www.freepik.com) from [www.flaticon.com](https://www.flaticon.com)\n- **Proxy** icon made by [Freepik](http://www.freepik.com) from [www.flaticon.com](https://www.flaticon.com)\n- **SSR Server** icon made by [Nhor Phai](https://www.flaticon.com/authors/nhor-phai) from [www.flaticon.com](https://www.flaticon.com)\n- **Chrome** icon made by [Pixel perfect](https://icon54.com) from [www.flaticon.com](https://www.flaticon.com)\n\n\n## Install Google Chrome\n\n\u003e Skip this step if you has install chrome browser\n\n```bash\ncurl -sL https://raw.githubusercontent.com/ciao-chung/ciao-ssr/develop/Meta/install-chrome.sh | bash\n```\n\n## Setup/Start server\n\n**Installation**\n\n```bash\nyarn global add ciao-ssr\n```\n\n**Start server**\n\n```bash\nciao-ssr --config=/file-to-your/config.json\n```\n\n**Clean cache**\n\n```bash\nciao-ssr --clean\n```\n\n## Configuration\n\n\u003e config json\n\n**Example**\n\n```json\n{\n  \"allowOrigin\": [\n    \"http://localhost:8081\", \"https://foo.bar\"\n  ],\n  \"cache\": {\n    \"ttl\": 60,\n    \"maxsize\": 1000\n  },\n  \"debug\": true\n}\n```\n\n* port(optional): **Number**, port of Node.js express app, default is 3000.\n* host(optional): **String**, host of Node.js express app, default is 'localhost'.\n* allowOrigin(required): **String/Array**, allow origin, you can set it as * if you don't want to limit any origin.\n* 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.\n* cache(optional): **Object**, configure cache feature.\n  * ttl(optional): **Number**, time to life of cache(minutes), default is 1 minute.\n  * maxsize(optional): **Number**, maxsize of cache file on disk(Kilobyte), default is 1MB.\n  * path(optional): **String**, cache file store path, default is 'cache'.\n   * driver(optional): **String**, default is file, here are available drivers.\n     - file\n     - redis\n  * redisHost(optional): **String** redis host(default is \"localhost\"), it only work when redis driver. \n  * redisPort(optional): **String** redis port(default is \"6379\"), only work when redis driver. \n  * redisPass(optional): **String** redis password(default is null), only work when redis driver.\n* debug(optional): **Boolean**, debug mode, it will open chrome without headless mode.\n* launchOptions(optional): **Object**, you can setup any custom puppeteer [launch option](https://goo.gl/zoshDo) by this property \n\n## Client side(web)\n\n### Installation\n\n```bash\nyarn add ciao-ssr-client\n```\n\n### Copy proxy(.htaccess) and middleware(ssr.php) to web root\n\nYou can find them in node_modules/ciao-ssr-client\n\nOr copy here\n\n**.htaccess**\n\n```apacheconfig\n\u003cIfModule mod_rewrite.c\u003e\n  RewriteEngine On\n  RewriteBase /\n\n  RewriteCond %{HTTP_USER_AGENT} !(firefox|chrome|safari|msie|edge|opera) [NC]\n  RewriteCond %{REQUEST_FILENAME} !-f\n  RewriteRule ^(.*)$ ssr.php [L]\n\n  RewriteRule ^index\\.html$ - [L]\n  RewriteCond %{REQUEST_FILENAME} !-f\n  RewriteCond %{REQUEST_FILENAME} !-d\n  RewriteRule . /index.html [L]\n\u003c/IfModule\u003e\n```\n\n**ssr.php**\n\n```php\n\u003c?php\n\n$ssrHost = 'https://ssr.server';\n$host = $_SERVER[\"REQUEST_SCHEME\"].'://'.$_SERVER[\"SERVER_NAME\"];\n$user_agent = urlencode($_SERVER['HTTP_USER_AGENT']);\n$port = '';\n\nif($_SERVER[\"REQUEST_SCHEME\"] == 'http' \u0026\u0026 $_SERVER[\"SERVER_PORT\"] != 80){\n    $port = ':'.$_SERVER[\"SERVER_PORT\"];\n}\n\nif($_SERVER[\"REQUEST_SCHEME\"] == 'https' \u0026\u0026 $_SERVER[\"SERVER_PORT\"] != 443){\n    $port = ':'.$_SERVER[\"SERVER_PORT\"];\n}\n$requestUrl = $host.$port.$_SERVER['REQUEST_URI'];\n$result = json_decode(file_get_contents($ssrHost.'/render?url='.$requestUrl), true);\n\nif(!$result || !$result['statusCode']) {\n    header(\"HTTP/1.0 404 Not Found\");\n    die;\n}\n\nhttp_response_code($result['statusCode']);\necho $result['content'];\n```\n\n\n### Use client library in web\n\nWe provide a client side library to trigger server side render service\n\n```javascript\nimport ServerSideRenderClient from 'ciao-ssr-client'\nServerSideRenderClient()\n\n// when your all async data are ready and render\nSSR.done()\n\n// when your page is in error type\nSSR.error()\n\n// when you want to custom error status code in error page\nSSR.error(403)\n```\n\n## Apache configuration\n\n**Enable apache rewrite/proxy/proxy_http modules**\n\n```bash\nsudo a2enmod rewrite\nsudo a2enmod proxy\nsudo a2enmod proxy_http\nsudo service apache2 restart\n```\n\n**Setup domain**\n\n```apacheconfig\n\u003cVirtualHost *:80\u003e\n    ServerName example.com\n    ServerAlias www.example.com\n    ProxyRequests Off\n    ProxyPreserveHost On\n    ProxyVia Full\n    \u003cProxy *\u003e\n        Require all granted\n    \u003c/Proxy\u003e\n    \u003cLocation /\u003e\n        ProxyPass http://localhost:3000/\n        ProxyPassReverse http://127.0.0.1:3000\n    \u003c/Location\u003e\n\u003c/VirtualHost\u003e\n```\n\n**Enable domain and restart apache**\n```bash\nsudo a2ensite example.com.conf\nsudo service apache2 restart\n```\n\n## Manage service with PM2\n\n[PM2](http://pm2.keymetrics.io) is an advanced Node.js process manager.\n\nYou can manage server side render service easily by using PM2.\n\n**Installation**\n\n```bash\nsudo yarn global add pm2\n```\n\n**Management**\n\n```bash\n# start service\npm2 start ciao-ssr --name=\"ssr\" -- --config=/file-to-your/config.json\n\n# stop service\npm2 stop ssr\n\n# delete service\npm2 delete ssr\n\n# show status\npm2 status ssr\n\n# show log\npm2 log ssr\n```\n\n## Start With Docker\n\nThis service will be started by pm2 when your container start\n\nJust setup port and config json file of your local host\n\n```bash\n# build image\ndocker-compose build --no-cahce\n\n# run\ndocker-compose up -d\n\n# exec\ndocker exec ssr /bin/bash\n\n# start service with pm2 in container\npm2 start ciao-ssr --name='ssr' -- --config=/ssr-config/config.json --watch \u0026\u0026 pm2 save\n```\n\n** Volume **\n\ndocker folder will mount as docker volume.\n\nyou should setup docker/config.json to configure your SSR service\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fciao-chung%2Fciao-ssr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fciao-chung%2Fciao-ssr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fciao-chung%2Fciao-ssr/lists"}