[labs/ssr] Add a serverhtml function, for templates that are only rendered on the server#4382
[labs/ssr] Add a serverhtml function, for templates that are only rendered on the server#4382
Conversation
🦋 Changeset detectedLatest commit: 53fb2bc The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
📊 Tachometer Benchmark ResultsSummarynop-update
render
update
update-reflect
Resultsthis-change
render
update
update-reflect
this-change, tip-of-tree, previous-release
render
update
nop-update
this-change, tip-of-tree, previous-release
render
update
this-change, tip-of-tree, previous-release
render
update
update-reflect
|
|
The size of lit-html.js and lit-core.min.js are as expected. |
jimsimon
left a comment
There was a problem hiding this comment.
Are there any security implications with using this new API? If so, it might be a good idea to add that info to the README.
Also, do we need to update the website docs?
AndrewJakubowicz
left a comment
There was a problem hiding this comment.
This is amazing!
augustjk
left a comment
There was a problem hiding this comment.
Very nice! I just have minor nits, mostly around docs.
Good point! Threw an error in that case and added a test. |
packages/labs/ssr/README.md
Outdated
|
|
||
| `serverhtml` templates can be composed, and combined, and they support almost all features that normal Lit templates do, with the exception of features that don't have a pure HTML representation, like event handlers or property bindings. | ||
|
|
||
| `serverhtml` templates can only be rendered once, so they can't be updated on the client. However if you render a normal Lit template inside a serverhtml template, then it can be hydrated and updated. Likewise, if you place a custom element inside a serverhtml template, it can be hydrated and update like normal. |
There was a problem hiding this comment.
Nit–non blocking docs. Can always be addressed in followup.
"serverhtml templates should only be rendered once, so they can't be updated on the client.".
This could be misconstrued as: you can use them somehow on the client as long as they are only rendered once. May be worth clarifying again here that serverhtml templates throw if they are used on the client.
There was a problem hiding this comment.
Ah, good point! Did another pass
packages/labs/ssr/README.md
Outdated
| `serverhtml` templates can only be rendered once, so they can't be updated on the client. However if you render a normal Lit template inside a serverhtml template, then it can be hydrated and updated. Likewise, if you place a custom element inside a serverhtml template, it can be hydrated and update like normal. | ||
|
|
||
| ```js | ||
| import {html} from 'lit'; |
There was a problem hiding this comment.
This import is unused in this file and can be removed.
| import {html} from 'lit'; |
| }); | ||
| } else if ( | ||
| !hydratable && | ||
| /^(title|textarea|script)$/.test(node.tagName) |
There was a problem hiding this comment.
Should style be added here. (It's also handled as a raw text element by lit-html)?
There was a problem hiding this comment.
Good point! Treating similarly to <script>, with unsafeHTML as the escape hatch.
|
|
||
| if (partIndex !== result.values.length) { | ||
| if (partIndex !== result.values.length && hydratable) { | ||
| throwErrorForPartIndexMismatch(partIndex, result); |
There was a problem hiding this comment.
Why are part index mismatches ok with server templates?
There was a problem hiding this comment.
Ah, I think that was from an old and worse prototype! Thank you for catching this!
|
|
||
| /** | ||
| * Returns true if the given node is a <script> node that the browser will | ||
| * automatically executeif it's rendered on server-side, outside of a |
There was a problem hiding this comment.
Nit: executeif -> "execute if"
| * features that don't have a pure HTML representation, like event handlers or | ||
| * property bindings. | ||
| * | ||
| * `serverhtml` templates can only be rendered once, so they can't be updated |
There was a problem hiding this comment.
"can't be updated on the client". Maybe here is where we add the text around "can't be used on the client at all".
A serverhtml template seems like it works fine to render both full pages and fragments, from doctype on down. If we discover a need for a document template later, we can add that API.
But not server templates inside normal templates (currently). Also add integration tests of partial hydration of client side templates inside a server side template.
Co-authored-by: Augustine Kim <augustinekim@google.com>
8c6ce54 to
53fb2bc
Compare
| Here's an example that shows how to use a serverhtml template to render a full document, and then lazily hydrate both a custom element and a template: | ||
|
|
||
| ```js | ||
| import {render, serverhtml} from '@lit-labs/ssr'; |
There was a problem hiding this comment.
I think like with lit-html/static.js exporting just html, we should probably name this just html too. If users want to rename it they can do:
import {render, html as serverHtml} from '@lit-labs/ssr';With the serverhtml name, they'll need to rename it if they want to get automatic syntax highlighting:
import {render, serverhtml as html} from '@lit-labs/ssr';and I think that'll be a fairly common case. I suspect that few, if any, files will import both client and server html tags. Instead server files would import client functions that use the client html in their own module.
|
|
||
| ## Server-only templates | ||
|
|
||
| You can also write templates that will only render on the server. These templates can be used for rendering full documents, including the doctype, and rendering into elements that Lit normally cannot, like `<title>`, `<textarea>`, `<template>`, and non-executing `<script>` tags like `<script type="text/json">`. They are also slightly more efficient than normal Lit templates, because the generated HTML doesn't need to include markers for updating. |
There was a problem hiding this comment.
The "non-executing <script> tags" bit isn't clear to me. Can you render to executing script tags?
|
|
||
| You can also write templates that will only render on the server. These templates can be used for rendering full documents, including the doctype, and rendering into elements that Lit normally cannot, like `<title>`, `<textarea>`, `<template>`, and non-executing `<script>` tags like `<script type="text/json">`. They are also slightly more efficient than normal Lit templates, because the generated HTML doesn't need to include markers for updating. | ||
|
|
||
| `serverhtml` templates can be composed, and combined, and they support almost all features that normal Lit templates do, with the exception of features that don't have a pure HTML representation, like event handlers or property bindings. |
There was a problem hiding this comment.
I think it'd be good to spell out the limitations if they're short. It's that they can't set properties, add event listeners, or use element directives, yeah? It might also be good to spell out some more of the the things they can do that make them useful, mainly: escaping, handling arrays, and directives?
| const [, prefix, caseSensitiveName] = /([.?@])?(.*)/.exec( | ||
| name as string | ||
| )!; | ||
| if (!hydratable) { |
There was a problem hiding this comment.
In hot code I prefer direct comparisons, especially if code size isn't a concern, like if (hydratable === false)
No description provided.