Filed under "it's likely hopeless, but..."
I'm beginning an exploration of LitElement and web components. I've been heavy in Angular, React, Gatsby, and HyperApp. Since I'm currently deep in Gatsby, I'm thinking about SSR, PRPL, and "first render".
More specifically, I come from Python. It's hard if you're not running Node on the server and get SSR and first render. This document talks about it.
Let's say we an old-school counter:
<body>
<div class="counter">
<h1>Counter</h1>
<p id="counter-value">0</p>
<button id="counter-increment">Increment</button>
</div>
</body>
...with counter.js
loaded to attach to the button and "do some stuff". It has an
important property: on page load, you have a counter, even without JS enabled
in the browser. Thus "first render" is nice.
SSR system let you do a nice, modern web component, without losing "first render". You have, for example, a HyperApp view. You render it on the server in Node and get a string, which you insert into the HTML of the page. It loads into the DOM. Later, JS kicks in, runs, and VDOM diffs into that existing node.
lit-html-server
does this. A Node server renders the component to a string
or stream, server side. When a browser goes to a URL, it can get the "first
render" of the component without any JS needed.
Benefits:
- Very fast initial load, since no JS evaluation is needed
- SEO
- The same implementation (template, logic) is used on server and client
Drawbacks:
- Well, that's the next section :)
This is great if Node is everywhere. I'm a Python guy. I'm interested in Python playing in this new PRPL world. There's a Python-> JS "transpiler" called Transcrypt. I worked on an SSR demo with Hyperapp.
But it still suffers from the dilemma. You either:
- Give up first render, or
- Maintain a Python template and a JS template, or
- You write your own template/view system in Python and let Transcrypt generate a JS-compatible version
More specifically...I could use Transcrypt to write Python that generated a
LiteElement
class. But I couldn't use Python to evaluate that to a string,
server-side.
It's likely hopeless. But for discussion, maybe there's machinery that could do it.
Imagine a web component <template>
embedded in a page, ready for use. Imagine
that template, without change, was used Python-side to do first render and
JS-side for hydration. Imagine the initial-render logic was in Python, transpiled
using Transcrypt, and thus its initial render to a string could happen server side.
Where would it fail? The expression language for substitution is JS. Maybe one could write those in Python and have Transcrypt convert a Python expression into an ES6 one. Template parsers suck.
Perhaps one could use TemplateInstantiation
as the substitution language, moving it
out of JS and into web standards. Polymer has an implementation. But it seems idle
and rarely-mentioned.
Perhaps there's some other idea I haven't thought of, some way to use web components and machinery (I'm new to this.)
Or, perhaps SSR and "first render" will always reside in the world of Node, and no other programming languages can participate.
This is an interesting read. I did not know about Transcrypt, thanks for that. We have a similar situation. We have Python engineers on a team trying to consumer our web component library, written in Stencil. The Stencil components do indeed load but there is a "flash" where the component is hidden before the javascript kicks in and renders everything nicely. Was wondering if there was a way to have Python prerender the components along with the response of the page.