Skip to content

Instantly share code, notes, and snippets.

@pauleveritt
Last active June 3, 2022 07:52
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pauleveritt/07591b37c82149b9a9b2ca4b9d26c3aa to your computer and use it in GitHub Desktop.
Save pauleveritt/07591b37c82149b9a9b2ca4b9d26c3aa to your computer and use it in GitHub Desktop.
LitElement and Python SSR

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.

A Counter: Old School

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.

Dehydration and Hydration

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 :)

Python and SSR/First Render

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.

LitHtml and Web Components

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.

@trazek
Copy link

trazek commented Jun 24, 2021

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.

@pauleveritt
Copy link
Author

@trazek Yes, I've worked quite a bit on preliminary stuff for what you are describing. Components that can render in Python on the server and re-render in JS in the browser, same original source code.

I'm not sure it will every be a fulfilling developer experience. Also, Transcrypt has ground to a halt in the last 18 months.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment