amaury_bouchard
Joined 8 months ago
Joined 8 months ago
µJS now resolves URLs using the native URL constructor and compares origin against window.location.origin. This means all same-origin URLs are correctly recognized as internal: - Absolute URLs: https://domain:port/page - Relative URLs: ../page.html, page.html - Local paths: /page (already worked)
Hash-only links (#section) are intentionally left to the browser for native anchor scrolling.
That said, the vast majority of websites are purely transactional: click a link, load a page; submit a form, load a page. For those, there's little reason to add a full frontend framework. HTML-over-the-wire can improve responsiveness without adding complexity.
That said, proper support for relative paths is on the roadmap.
Your concern about `mu-method="delete"` is valid. Without JS, the browser will fall back to the form's native method (usually GET or POST). The classic solution is the `_method` hidden field pattern: the form submits POST with a `_method=DELETE` field, and the server reads that field to route the request correctly. µJS doesn't need to implement anything special for this, it's a server-side convention
On relative paths: the current behavior is intentional for simplicity. µJS checks whether the URL starts with a slash (but not a double slash) to identify internal links. No one has reported this as an issue so far, but it's a valid feature request and I'll keep it in mind for a future version.
On the integrity attribute: the reason it was missing is that the library was evolving quickly and the hash would have changed with every release. Now that it's stable, I'll add it.
Here's what I deliberately left out compared to Turbo (~25KB gzip) and htmx (~16KB gzip):
- No client-side template/extension system. htmx has a full extension API, header-based control flow (HX-Trigger, HX-Redirect, HX-Reswap...), and dozens of response headers the server can use to command the client. µJS has 5 custom headers total; the server returns HTML, the client renders it.
- No CSS selector-based targeting in attributes. htmx lets you write hx-target="closest tr", hx-target="find .result", hx-target="next div" with a mini query language. µJS uses plain CSS selectors only (mu-target="#id"), no traversal keywords.
- No built-in transition/animation classes. htmx adds/removes CSS classes during swaps (htmx-settling, htmx-swapping, htmx-added) with configurable timing. Turbo has turbo-preview, transition classes, etc. µJS defers to the native View Transitions API: zero animation code in the library, and it falls back silently.
- No client-side cache or snapshots. Turbo keeps a page cache for "instant" back-button rendering and manages preview snapshots. µJS stores only scroll position in history.state and lets the browser's own cache + fetch() handle the rest.
- Patch mode simpler than Turbo Frames. Turbo has <turbo-frame>, a custom element with lazy-loading, src rewriting, and frame-scoped navigation. µJS handles multi-fragment updates via patch mode (mu-mode="patch") with regular HTML elements. No custom elements, no frame concept. It's simpler but it works perfectly.
- No request queuing or throttling. htmx has hx-sync with queuing strategies (queue, drop, abort, replace). µJS simply aborts the previous in-flight request. One request at a time per navigation.
- No form serialization formats. htmx supports JSON encoding (hx-encoding), nested object serialization, etc. µJS uses the browser's native FormData for POST and URL params for GET. That's it.
- No JavaScript API surface to speak of. htmx exposes htmx.ajax(), htmx.process(), htmx.trigger(), event details, etc. µJS exposes mu.init(), mu.fetch(), mu.render(), and a few setters and a few events. The goal is that you shouldn't need the JS API — the HTML attributes should be enough.
What I kept: the features that cover 90% of real-world use cases. AJAX navigation, 8 injection modes, multi-fragment patch, morphing (via Idiomorph), SSE, prefetch, forms with all HTTP verbs, triggers with debounce/polling, progress bar, history/scroll management. Just without the layers of abstraction around them.
The philosophy: if the browser already does it (View Transitions, FormData, fetch, AbortController, history API), don't reimplement it.
My personal work spans software, games, and tools (all published under open source licenses): - Temma (https://www.temma.net): PHP MVC framework, easier than the big frameworks, more useful than the micro-frameworks - µJS (https://mujs.org): Lightweight AJAX navigation library, 5KB alternative to Turbo and htmx - µCSS (https://mucus.org): Full-featured CSS framework, based on PicoCSS - Arkiv (https://github.com/Digicreon/Arkiv): Easy-to-use backup and archive tool - Dispak (https://github.com/Digicreon/Dispak): Extensible tool for managing Git repositories and project deployment - Rolis (https://www.rolis.net): A list of open-sourced tabletop role playing games, and multi-engine open-source scenarios - Pandocreon Menhir (http://www.pandocreon.com/jeux/menhir/): Award-winning boardgame