How to perform server-side rendering in Verge3D — Soft8Soft
Description: With Verge3D you can do both client-side (in the web browser) or server-side rendering. The latter can be employed if the user has low-end hardware or slow network, or to provide the best quality possible, yet still having configurable content.

# Server-Side Rendering

From this section you will find out how to run Verge3D on server to perform rendering in headless mode. This feature can be employed if the user has low-end hardware or slow network, or to provide the best quality possible, yet still having configurable content.

- Running Chrome on server in headless mode
- Using Node.js and Puppeteer
- Next Steps

#

## Running Chrome on server in headless mode

You can run Google Chrome (or Chromium if you prefer it) in headless mode, e.g without using screen or GUI. To do this, specify the --headless option:

`google-chrome --headless --use-gl=egl https://www.soft8soft.com/webglreport`

The --use-gl=egl option enables accelerated GPU rendering in headless mode:

Unmasked Vendor/Renderer lines say that Chrome Headless uses real GPU of the target system

By default headless command does nothing meaningful. To allow remote debugging of the page, specify --remote-debugging-port=9222 option:

`google-chrome --headless --use-gl=egl --remote-debugging-port=9222 https://www.soft8soft.com/webglreport`

then run regular desktop Chrome to inspect the page. Configure Discover network targets then click inspect:

Another important feature of headless mode is ability to take screenshots:

`google-chrome --headless --use-gl=egl --screenshot https://www.soft8soft.com/webglreport`

or generate PDF files:

`google-chrome --headless --use-gl=egl --print-to-pdf https://www.soft8soft.com/webglreport`

Check out the official documentation from Google for more info about Chrome Headless.

#

## Using Node.js and Puppeteer

Sometimes you need more control of the Chrome Headless mode. For example, you might need taking screenshots in automated manner, or implement some client-server routine for requesting screenshots from the server. For that, Google developed a nice Node.js library called Puppeteer.

To install it, simply create the file with the following contents inside some folder and name it package.json (or simply download it from here):

`{ "description": "Headless Chrome tests with Puppeteer", "dependencies": { "commander": "*", "puppeteer": "*" } }`

Then go to that directory and execute:

`npm install`

to install Puppeteer and all required dependencies (including pre-built binary of the Chromium browser).

Use the following Node.js script to automate taking screenshots of your Verge3D apps (download):

`#!/usr/bin/node import { program } from 'commander'; import puppeteer from 'puppeteer'; program .option('-u, --url [url]', 'URL to open', 'http://localhost:8668/') .option('-s, --screenshot-path programmers_guide/Server-Side-Rendering', 'A path where to save the screenshot', './screenshot.png') .option('-t, --timeout [ms]', 'Timeout after page loading before taking the screenshot', function(val) { return parseInt(val); }, 2000) .option('-W, --viewport-width [px]', 'The width of the viewport', function(val) { return parseInt(val); }, 1920) .option('-H, --viewport-height [px]', 'The height of the viewport', function(val) { return parseInt(val); }, 1080) .parse(process.argv); async function run() { console.log('Launching headless Chrome...'); const browser = await puppeteer.launch({ args: ['--use-gl=egl'] }); console.log('Opening new page...'); const page = await browser.newPage(); const opts = program.opts(); console.log('Setting viewport size to ' + opts.viewportWidth + 'x' + opts.viewportHeight + '...'); await page.setViewport({ width: opts.viewportWidth, height: opts.viewportHeight }); console.log('Opening ' + opts.url + ' ...'); await page.goto(opts.url); console.log('Waiting for ' + opts.timeout + 'ms ...'); await timeout(opts.timeout); console.log('Taking screenshot...'); await page.screenshot({ path: opts.screenshotPath, type: 'png' }); console.log('Page\'s screenshot saved to ' + opts.screenshotPath); console.log('Closing Chrome...'); await browser.close(); } function timeout(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }; run();`

Place the code as screenshot.js in the same directory you installed Puppetter and launch:

`node screenshot.js -u https://cdn.soft8soft.com/demo/blender/spinner/spinner.html`

to take screenshot of the Spinner application and save it as screenshot.png image:

The screenshot script comes with a variety of useful options. To get help, run it with the -h argument:

`node screenshot.js -h`

With Puppeteer you can also capture videos of your Verge3D renderings. See here for more info.

#

## Next Steps

In the screenshot.js script we use the timeout property to wait for app loading. In the real-world scenario you might need to provide a more advanced awaiting routine (download):

`console.log('Waiting for application loading...'); await page.evaluate(() => { return new Promise(resolve => { const interval = setInterval(() => { if (window.v3d.apps !== undefined && window.v3d.apps.length > 0) { clearInterval(interval); resolve(); } }, 0); }); }); await page.evaluate(() => { const app = window.v3d.apps[0]; return new Promise(resolve => { app.addEventListener('afterRender', () => { resolve(); }); }); });`

Also, we did not cover any client-server interaction. For that you can implement a simple HTTP server or a more advanced WebSocket server.

## Got Questions?

Feel free to ask on the forums!