| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Social Media Photo by Andrii Ganzevych on Unsplash
A minimalistic library to create fast and reactive Web pages.
<!doctype html>
<script type="module">
import { html } from 'https://esm.run/uhtml';
document.body.prepend(
html`<h1>Hello DOM !</h2>`
);
</script>uhtml (micro µ html) offers the following features without needing specialized tools:
test in codepen
import { html, signal } from 'https://esm.run/uhtml';
function Counter() {
const count = signal(0);
return html`
<button onClick=${() => count.value++}>
Clicked ${count.value} times
</button>
`;
}
document.body.append(
html`<${Counter} />`
);If you are familiar with JSX you will find uhtml syntax very similar:
The main difference between uhtml and JSX is that fragments do not require <>...</> around:
// uhtml fragment example
html`
<div>first element</div>
<p> ... </p>
<div>last element</div>
`On top of JSX like features, there are other attributes with a special meaning:
All other attributes will be handled via standard setAttribute or removeAttribute when the passed value is either null or undefined.
Elements that contain data such as <script> or <style>, or those that contains text such as <textarea> require explicit closing tag to avoid having in between templates able to break the layout.
This is nothing new to learn, it's just how the Web works, so that one cannot have </script> within a <script> tag content and the same applies in here.
In debugging mode, an error telling you which template is malformed will be triggered in these cases.
Useful for developers but never really relevant for end users, comments are ignored by default in uhtml except for those flagged as "very important".
The syntax to preserve a comment in the layout is <!--! important !-->. Every other comment will not be part of the rendered tree.
html`
<!--! this is here to stay !-->
<!--// this will go -->
<!-- also this -->
`The result will be a clear <!-- this is here to stay --> comment in the layout without starting and closing !.
There are two kind of "logical comments" in uhtml, intended to help its own functionality:
The hole type might disappear once replaced with different content while persistent fragments delimeters are needed to confine and/or retrieve back fragments' content.
Neither type will affect performance or change layout behavior.
import {
// DOM manipulation
render, html, svg, unsafe,
// Preact like signals, based on alien-signals library
signal, computed, effect, untracked, batch,
// extras
Hole, fragment,
} from 'https://esm.run/uhtml';In details
The easiest way to start using uhtml is via CDN and here a few exported variants:
// implicit production version
import { render, html } from 'https://esm.run/uhtml';
// https://cdn.jsdelivr.net/npm/uhtml/dist/prod/dom.js
// explicit production version
import { render, html } from 'https://esm.run/uhtml/prod';
// https://cdn.jsdelivr.net/npm/uhtml/dist/prod/dom.js
// explicit developer/debugging version
import { render, html } from 'https://esm.run/uhtml/dev';
import { render, html } from 'https://esm.run/uhtml/debug';
// https://cdn.jsdelivr.net/npm/uhtml/dist/dev/dom.js
// automatic prod/dev version on ?dev or ?debug
import { render, html } from 'https://esm.run/uhtml/auto';
import { render, html } from 'https://esm.run/uhtml/cdn';
// https://cdn.jsdelivr.net/npm/uhtml/dist/prod/cdn.jsUsing https://esm.run/uhtml/cdn (or /auto) or the fully qualified https://cdn.jsdelivr.net/npm/uhtml/dist/prod/cdn.js URL provides an automatic switch to debug mode if the current page location contains ?dev or ?debug or ?debug=1 query string parameter plus it guarantees the library will not be imported again if other scripts use a different CDN that points at the same file in a different location.
This makes it easy to switch to dev mode by changing the location from https://example.com to https://example.com?debug.
Last, but not least, it is not recommended to bundle directly uhtml in your project because components portability becomes compromised, as example, if each component bundles within itself uhtml.
Another way to grant CDN and components portability is to use an import map and exclude uhtml from your bundler.
<!-- defined on each page -->
<script type="importmap">
{
"imports": {
"uhtml": "https://cdn.jsdelivr.net/npm/uhtml/dist/prod/cdn.js"
}
}
</script>
<!-- your library code -->
<script type="module">
import { html } from 'uhtml';
document.body.append(
html`Import Maps are Awesome!`
);
</script>Minification is still recommended for production use cases and not only for JS, also for the templates and their content.
The rollup-plugin-minify-template-literals is a wonderful example of a plugin that does not complain about uhtml syntax and minifies to its best uhtml templates in both vite and rollup.
This is a rollup configuration example:
import terser from "@rollup/plugin-terser";
import templateMinifier from "rollup-plugin-minify-template-literals";
import { nodeResolve } from "@rollup/plugin-node-resolve";
export default {
input: "src/your-component.js",
plugins: [
templateMinifier({
options: {
minifyOptions: {
// allow only explicit <!--! comments !-->
ignoreCustomComments: [/^!/],
keepClosingSlash: true,
caseSensitive: true,
},
},
}),
nodeResolve(),
terser(),
],
output: {
esModule: true,
file: "dist/your-component.js",
},
};The current pareser is already environment agnostic, it runs on the client like it does in the server without needing dependencies at all.
However, the current SSR story is still a work in progress but it's planned to land sooner than later.
| Back | FazBrowse Home | New Git URL |