Hacker News new | ask | show | jobs
by nickreese 700 days ago
Using this pattern has been a gift. It is really freeing to write templates without a framework and worrying about SSR.

Years back I dove completely in on Svelte and even wrote my own SSG that helped kick off the Islands/partial hydration crazy... Elder.js. It was fun, but burnt me out of open source.

Today, I only pull for a template language and deal with SSR/Hydration for pages that really need it.

I want JS projects that don't break 6 months after the last build. The way you get that is by not adding more dependencies and not chasing the latest craze.

3 comments

> I want JS projects that don't break 6 months after the last build

I was somewhat recently trying to get a 3 year old JS project working. I felt like I was alone in an Egyptian pyramid wondering if I had missed the funeral.

> I want JS projects that don't break 6 months after the last build. The way you get that is by not adding more dependencies and not chasing the latest craze.

I've settled on ``document.createElement()``: it's a bit rough visually, but that's pretty much the only downside (I've found the time gained with templates to be negligible in front of the overall development time).

A big bonus of dealing with genuine objects is that there's room to extend them to e.g. store additional state/data/handlers/etc., which might otherwise be cumbersome to be set via attributes & cie.

An even bigger and underappreciated bonus of dealing with objects is that you're working at the correct abstraction layer. Using templates that glue string together is doing the Wrong Thing, and this is how you get XSS (or outside of HTML, injection class vulnerabilities specific to what you're writing, e.g. SQL injection when gluing strings into queries).
By being imperative, you describe how to get to the state you desire. By being declarative, you split the concerns of “how it should be” and “how to get there”, which doesn’t come without downsides (abstractions are leaky) but does have its benefits: the latter logic you’d maintain in one place, and the former is usually easier to reason about.
I'm not talking about imperative vs. declarative, but about working at the level of language you're dealing with. Using string concatenation for building HTML or SQL is like doing arithmetic like "123" + "456" = "123456" -- you're using the wrong addition operator.
Describing the state by design implies not working at the same level as getting to that state, though—I’m not sure if there is some subtlety I’m missing—and to me there seem to be obvious benefits (and downsides, as mentioned above) to not explicitly manipulating DOM where I want to just describe how a page should be structured.
Perhaps this can help to fix the ideas: here's how you could create the HTML by manipulating the DOM (the code indentation mimics the HTML indentation):

   let p = document.createElement("span");
  
    let b = document.createElement("button");
    b.innerText = btnText;
    if (btnClass) b.classList.add(btnClass);
  
    let m = document.createElement("span");
    m.style.display = "none";
    m.classList.add(modalClass);
  
     let q = document.createElement("span");
     q.classList.add(modalContentClass);
  
      let c = document.createElement("button");
      c.innerText = "×";
      c.classList.add(modalBtnCloseClass);
  
      // r is an "external" HTMLElement
      r.classList.add(modalContentClass);
  
     q.append(c, r);
  
    m.appendChild(q);
  
   p.append(b, m);
It's not that different from writing the HTML (with or without a template). But IMO the great thing here is that, at the end of that chunk of code, you've got pointers to every node of interest. You can then register handlers, target arbitrary nodes in such handlers, without having to navigate through the HTML (e.g. by setting ``id`` or other attributes to help identify them, or by relying on a static HTML structure).

And as the parent points, this should prevent some amount of unexpected HTML injection.

There's still a separation between the view and the page structure.

For those looking for something more robust... this is where I'd look: https://github.com/kitajs/html.

Also Honojs (hono.dev) has a built in HTML function which is quite good and I've used extensively.

kitajs already being a fork of https://github.com/nicojs/typed-html . What makes this one more robust or stable then?