@lit-labs/ssr - Property binding server side? #4406
-
Hello everyone. I'm currently using It works fine with primitive types, but when I try to pass an object or array to the element, it breaks. I wrote some examples. Here's the code for the element, nothing fancy, only a simple LitElement with 2 properties, it renders the name and a list with the items. import { LitElement, html } from "lit";
import { repeat } from "lit/directives/repeat.js";
export class MyListElement extends LitElement {
static properties = {
items: { type: Array },
name: { type: String }
}
constructor() {
super();
this.name = 'Tony Stark';
this.items = ['Mark 42', 'Mark 43'];
}
render() {
return html`
<div>
<h1>${this.name}'s list</h1>
<ul>
${
repeat(
this.items,
(item) => html`<li>${item}</li>`
)
}
</ul>
</div>`;
}
}
customElements.define('my-list', MyListElement); Here's the server rendering the examples import express from 'express';
import { html } from 'lit';
import { render } from '@lit-labs/ssr/lib/render.js';
import { RenderResultReadable } from '@lit-labs/ssr/lib/render-result-readable.js';
const server = express();
server.use('/dist', express.static('dist'));
server.use((req, res, next) => {
res.renderTemplate = (template) => {
res.setHeader('Content-Type', 'text/html; charset=utf-8');
const readableResult = new RenderResultReadable(render(template));
readableResult.pipe(res);
}
next();
})
const myTemplate = html`
<html>
<head>
<script src="/dist/bundle.js"></script>
</head>
<body>
<h1>The list</h1>
<!-- Renders name correctly. -->
<my-list name=${'Example 1'}></my-list>
<!-- Does not renders the name correctly. -->
<my-list .name=${'Example 2'}></my-list>
<!-- Does not renders the element at all. -->
<my-list items=${['Example 3']}></my-list>
<!-- Does not render the items correctly. -->
<my-list .items=${['Example 4']}></my-list>
</body>
</html>
`;
server.get('/', (req, res) => {
res.renderTemplate(myTemplate);
});
server.listen(3000, () => {
console.log('Server is listening on port 3000');
}); Here's a git repo with the examples https://github.com/pedrolzoliveira/lit-property-binding-ssr/ It seems logical for me that the third example fails, because that's not how you should pass props to the elements in Lit. For the rest looks like it might be a problem with property bindings? Are we supposed to use it that way when rendering on the server? I'm looking for a way to make it works for some weeks now, in my project I was able to do that by converting the object/array to a string and them parsing it back to object/array. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
-
Hi! Thank you for asking this question. It definitely highlights a lack of good errors when hitting painful cases in Lit SSR. Issue 1: Your client side elements load too fast
This means that if you have server side rendered The solution to this is to not load your component until the initial render of the page is complete. Either lazy-load your component within the script, (e.g. with a dynamic import). Or add Issue 2: server.js is not server side rendering
|
Beta Was this translation helpful? Give feedback.
-
In addition to @AndrewJakubowicz 's detailed explanation of the issues, I do want to point out that property bindings on custom elements in regular The SSR render method allows for an option called This definitely is more clunky and might be better with a more framework like layer of abstraction which we currently don't have. So if you're able to serialize into attributes, that might be the easiest thing to do. |
Beta Was this translation helpful? Give feedback.
Hi! Thank you for asking this question. It definitely highlights a lack of good errors when hitting painful cases in Lit SSR.
I've attached to this comment the changes required to fix the issues you are seeing (found at the end).
Issue 1: Your client side elements load too fast
<script src='/dist/bundle.js'></script>
is located at the top of the HTML file, which blocks the HTML parser to fetch and execute your JavaScript. This results inmy-list
being completely loaded and ready to use before the HTML parser has started to render the body element.This means that if you have server side rendered
my-list
, the declarative shadow DOM will have already attached the shadowRoot and an error get…