#ASKTHEINDUSTRY 13: Can Web Components be rendered server-side?

Alessandro Menduni
Feb 23, 2017 · 3 min read

I feel you. Web Components have always been worrying me for they depend on JavaScript to kick in. If for whatever reason it fails to load or, even worse, it takes a lot of time to download and execute, nothing gets painted for ages.

A first take at the problem could be rendering skeletons, meaning using CSS to target a Web Component and draw placeholders that will then be replaced by the actual content, as soon as it arrives. This technique improves the perceived performance, however a couple of downsides come to mind:

1. If the JS completely fails to load, the user gets nothing. Just meaningless shapes and boxes.
2. SEO is probably killed (I guess?, not sure on this one)
3. It’s very limited in aesthetics, unless you also add dummy markup.

There might be another solution. A couple of days ago, Server Side Rendering came up. As you may recall, it is a technique that allows the server to send down an initial render of the page, so to speed up the First Paint. Can we do the same with Web Components?

Indeed we can. However, there are some challenges involved:

  1. First, you need a way to run your components’ definitions on the server. It’s not trivial, since global variables like document and HTMLElement are not available in Node.
  2. You need to parse the HTML and recognize the Web Components
  3. You need to bootstrap the components and let them render their content.
  4. Finally, you can send the rendered HTML to the client.

Step 2 and 3 have been taken care of by this really promising library: server-components.

Step 1 is the missing part. I experimented a bit and here is what I came up with:

First we’re going to require server-components and one of its dependencies: domino.

// Require dependencies
var domino = require( 'domino' );
var components = require( "server-components" );

Then, we expose HTMLElement globally and rename components.registerElement into document.registerElement.

// Set up globals
global.HTMLElement = domino.impl.HTMLElement;
global.document = {
registerElement: components.registerElement.bind( components )
};

We can now require the bundle containing our elements definitions

// Require elements
require( './public/bundle.js' );

Finally, we’ll set up an Express server and send the rendered HTML when requested

// Set up server
var app = express();
var home = fs.readFileSync( 'public/index.html' );
// Render page
app.get( '/', function( req, res ) {
components.renderPage( home )
.then( function( output ) {
res.send( output );
} );
} );

It surely is a very simple use case, but I think this might be the right path towards fast-loading Web Components based apps.

You can find the code on GitHub


I read each and every comment, and look forward to answer to your questions! This piece is part of the #ASKTHEINDUSTRY project, which is supposed to be about your questions :) Drop a comment if there is anything I can help you with!

West Wing Solutions

Alessandro Menduni

Written by

I Help Online Businesses CONVERT High Traffic Volume Into Customers | https://www.westwingsolutions.com

West Wing Solutions

Learning material for eCommerce owners eager to explore the science behind building a successful online product.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade