Closed WebReflection closed 5 months ago
Thanks! It works well! Maybe you will be interested in the final product.
I used uhtml/ssr a bit more, and... my code ended up like this:
/**
* @function
* @param {import('uhtml/keyed')} */
module.exports = ({ Hole, attr, html, htmlFor, render, svg, svgFor, document }) => ({
root() {
const body = html`
<p>Hi!</p>
`
return html`<head><link rel="stylesheet" href="/all.css" /></head><body>${body}</body>`
}
})
given how document
is only available at run-time, this API is not .. great. Also, the return type of initSsr
is inferred as any
in vscode; not sure why.
Is it possible for a html` template to exist without
document`?
@iacore I am not sure I am following ... see the test example: https://github.com/WebReflection/uhtml/blob/main/test/ssr.mjs
you can have one or more documents (one per page to render if you want) and I can't provide a global document as that's hostile.
I have removed types and used the suggested way to export things in there ... I don't know why TS doesn't understand that but I wonder if you are on latest TS.
As follow up questions:
document
if shared? it leads to weird concurrent cases if all pages share the same documenthtml
out of a module? if that's the case you can always create your own .cjs
file and do something like:module.exports = typeof process === 'object' ?
require('uhtml/ssr')('...') :
{ ...require('uhtml/keyed'), document };
This uhtml.cjs
would give you same exports if you are either on Node/Bun or Browser.
Make it an .mjs
or a .js
with type: "module"
if you're after ESM.
Would this improve the API?
As follow up questions:
* what/how do you want to use the `document` if shared? it leads to weird concurrent cases if all pages share the same document
I don't want to use document
if shared, although node.js is single-threaded so this would not be a problem if there is only one render
call.
* is the issue that you can't have globally available `html` out of a module?
This is the issue. uhtml does not allow components to be defined with a generic html
function; it has to be bound to a document.
In preact, the components are defined with JSX/hyperscript, so this is not a problem.
So my question is, can Hole
live without document
? Is this limitation of uhtml's design?
For the types, I will fix it.
you need to import html
and render
regardless of the SSR story, that's how modules work in JS and uhtml is just a module so I keep not being sure I follow the question.
The Hole is just a class and represents entries expected as holes within the render
logic. Neither the render
nor the uhtml
or other exports are global but where do you have an issue with it? JSX requires transpilation (even in Bun) and it works with pragma functions that default to React
namespace which is also global ... none of this is part of uhtml as the whole point is to use standards (ESM, template literal tags, no tools needed) but your files need to import those utilities and I've suggested a way to do so, out of other ways, if sharable components is what you are after.
Here is a more concrete example.
Here's a file, abc.js
.
import { html, render } from 'uhtml'
html`<h1>a</h1>`
If I run it with node, it doesn't work.
❯ node abc.js
file:///home/user/computing/lib/js/uhtml/esm/persistent-fragment.js:30
export class PersistentFragment extends custom(DocumentFragment) {
^
ReferenceError: DocumentFragment is not defined
at file:///home/user/computing/lib/js/uhtml/esm/persistent-fragment.js:30:48
at ModuleJob.run (node:internal/modules/esm/module_job:222:25)
at async ModuleLoader.import (node:internal/modules/esm/loader:323:24)
at async loadESM (node:internal/process/esm_loader:28:7)
at async handleMainPromise (node:internal/modules/run_main:120:12)
Node.js v21.7.2
Can this limitation be overcome?
IMO, the definition of a component (even as simple as html`\
I think I will read the source code of uhtml to understand how it works.
Can this limitation be overcome?
yes, that's why you want either uhtml/init
or uhtml/ssr
... if you want that to work in both client or server you need to create your own file as explained in here https://github.com/WebReflection/uhtml/pull/114#issuecomment-2056150399 as I can't provide uhtml without a Document
on NodeJS side and you don't want a shared document for multiple pages purpose unless you use a template for the <head>
part and you only render different bodies, that works too, still you gotta provide a document.
If you are OK in polluting the global context then in node only:
import initSSR from 'uhtml/ssr';
const { document } = initSSR('...');
Object.assign(globalThis, {
document,
DocumentFragment: document.createDocumentFragment().constructor
});
Then you should be able to use that file and eventually serve document.toString()
after render(document.body, () => html
your thing)
edit P.S. that entry point should run before the rest of your node app runs or use .cjs
instead so that the resolution of each module is incremental.
@iacore another alternative is to use importMap so that on browser you get just that while on node you get your file that bootstrap the SSR and exports then everything it offers, after placing the document
and the fragment to the global, then you should have a seamless exprience. I can't remember the current state of importMap in node though.
What I do in my tests is like this: https://github.com/WebReflection/uhtml/blob/main/test/modern.mjs#L9-L13
What I do in my tests is like this: https://github.com/WebReflection/uhtml/blob/main/test/modern.mjs#L9-L13
Thanks! This is exactly what I'm looking for!
This MR brings forward the hydro branch https://github.com/WebReflection/uhtml/pull/113 as I got stuck but also I am not sure anymore I was doing the right thing ... but as I don't want to get stuck, it made sense to at least provide an
uhtml/ssr
export and fix some gotcha with the persistent fragment.This MR also fixes https://github.com/WebReflection/uhtml/issues/111 by removing TypeScirpt as a whole and provide just JSDoc TS for the provided files. I hope this won't break anyone out there but as types were buggy this can land as minor as it doesn't break anything, it adds a new
uhtml/ssr
export, and it should improve TS / types in general.The hydro branch is on hold until I have both head and time to get that right.