[HN Gopher] VanillaJSX.com
       ___________________________________________________________________
        
       VanillaJSX.com
        
       Author : novocantico
       Score  : 497 points
       Date   : 2024-08-16 19:01 UTC (1 days ago)
        
 (HTM) web link (vanillajsx.com)
 (TXT) w3m dump (vanillajsx.com)
        
       | arjvik wrote:
       | What benefit does the virtual DOM add?
        
         | spoiler wrote:
         | DOM interactions (read, writes) are synchronous, they're very
         | slow, and it must happen on the main thread. This can cause the
         | browser tab to freezing if access and updates aren't carefully
         | "curated" (ie you don't want to read-check-then-write in a
         | tight loop; or even write too often, even if it's the same
         | value).
         | 
         | It can also simplify some stuff surrounding event handling (but
         | that's not it's main goal I think)
         | 
         | So people wrote various ways to defer/batch/denounce updates.
         | 
         | Virtual DOM is a general solution/implementation. It's not the
         | only one, but I think you always need at least a tiny runtime
         | to avoid too much DOM access (ie Svelte, Solid JS are fairly
         | minimal)
        
           | meiraleal wrote:
           | > but I think you always need at least a tiny runtime to
           | avoid too much DOM access
           | 
           | Unless you use lit-html, which has a very efficient diffing
           | algorithm that only updates the nodes that have changed.
        
             | smallnamespace wrote:
             | How is that done without a vdom?
        
               | meiraleal wrote:
               | Lit-html uses template literals for that
               | 
               | https://lit.dev/docs/libraries/standalone-templates/
               | 
               | "lit-html lets you write HTML templates in JavaScript
               | using template literals with embedded JavaScript
               | expressions. lit-html identifies the static and dynamic
               | parts of your templates so it can efficiently update just
               | the changed portions."
        
               | smallnamespace wrote:
               | A a high level there's not much difference between
               | template literals and JSX, they are both syntax-sugary
               | ways to represent trees of essentially function calls.
               | 
               | > efficiently update just the changed portions
               | 
               | Since actually applying each change to the real DOM is
               | too slow, the only way to efficiently update is to batch
               | changes and then apply the delta to the actual DOM.
               | 
               | That means we need to keep track of some state, namely
               | the previously applied state and the current goal state,
               | which you then compare.
               | 
               | Now, you may have noticed that we've just independently
               | invented the concept of diffing. And the extra state that
               | needed to be tracked can be given a spiffy name, like
               | "virtual DOM", since it's like the DOM, but not the real
               | thing.
               | 
               | So, I'm quite unconvinced by Lit-html's claim that they
               | are able to efficiently mutate the DOM without using a
               | vDOM anywhere.
               | 
               | Either their method is not efficient (for example it
               | falls over for rapid updates), or there is a data
               | structure under the hood that is analogous to a vDOM,
               | even if they prefer to give that data structure a
               | different name.
        
               | meiraleal wrote:
               | Oh well, we gotta thanks the great developers of Lit-html
               | for making it transparent then. And a lot faster than
               | React.
               | 
               | https://krausest.github.io/js-framework-
               | benchmark/current.ht...
        
               | smallnamespace wrote:
               | Yes, looking it into it more, Lit-html is doing a few
               | things to make it all work:
               | 
               | 1. It leans on support for the <template> element from
               | browsers to hold fragments of HTML
               | 
               | 2. For most use cases, it has a more restricted
               | programming model compared to React or other vdom
               | libraries, because templates are not allowed to change
               | the shape (the tree structure of nodes) of the templated
               | DOM.
               | 
               | 3. For some cases where you want it to act more like
               | React (for example, dynamically picking an HTML tag) you
               | must use other mechanisms such as unsafeStatic. The docs
               | explicitly tell you this immediately triggers a re-render
               | = slow.
               | 
               | So I guess that answered my own curiosity: the vDOM is
               | mostly replaced by a collection of static templates that
               | don't need to be diffed, because the onus is on the dev
               | to write DOM fragments where the tree does not change.
               | 
               | This is a more restrictive model that what React gives
               | you, where you can generate any fragment tree, including
               | ones with different shapes, entirely programatically.
               | 
               | If you do want the tree's shape to change, then lit-html
               | isn't promising you good performance. You'll need to use
               | methods like unsafeStatic which are slow. All in all,
               | this is pushing more work off onto the developer.
               | 
               | Is this a good tradeoff? I think for most websites you
               | can probably work within Lit's programming model. But the
               | benchmarks you yourself linked points to many, many vDOM
               | libraries that are about as performant as Lit (including
               | React, whose main downside somewhat more memory usage)
               | and has a more convenient React-like programming model.
        
               | meiraleal wrote:
               | Thanks for the comprehensive analysis, quite interesting.
               | 
               | I disagree about the trade-off in convenience tho, React
               | programming model (especially related to managing state)
               | is quite confusing, verbose and error-prone.
               | 
               | Multiple useless re-renders are the norm.
               | 
               | useEffects inside the body of functions a very poor way
               | to manage the lifecycle of a component and this is way
               | simpler with Lit.
               | 
               | All in all, just for it to be more like React pre-15 I
               | would choose Lit.
        
         | samwillis wrote:
         | The virtual dom makes implementing a declarative templating
         | system easer, and declarative templates are easer for a
         | developer to reason about, and less error prone, than having to
         | mutate the dom directly.
         | 
         | People often mistakingly describe the vdom as faster than the
         | dom, this is incorrect. It would be faster than throwing away
         | the whole components dom and rebuilding, so the same templating
         | code building a new dom, rather than a vdom that's then diffed.
         | Hand crafter mutations will be faster than a vdom diff, simply
         | because the computer is doing les work, however much more error
         | prone.
        
           | spoiler wrote:
           | > People often mistakingly describe the vdom as faster than
           | the dom, this is incorrect.
           | 
           | You'll get better performance with _carefully crafted_ DOM
           | access, but that's easier said than done, especially on a
           | larger applications.
           | 
           | vDOM takes care of the "carefully crafted" part with some
           | trade offs, especially if it also defers rendering and
           | doesn't wccess the DOM on every update.
           | 
           | So yes, it's easier to write declarative UIs with it, but
           | it's also there to address common performance issues with
           | unchecked/eager DOM access. Even if you don't throw away the
           | whole tree and insert a new one, it can be very slow. Just
           | _reading_ from the DOM is slow _and_ everything stops while
           | that's being done too.
        
           | miki123211 wrote:
           | Virtual DOM is to classical JS what garbage collection is to
           | malloc and free.
           | 
           | Garbage collection is less efficient, but it is sometimes
           | very difficult to figure out exactly when a piece of memory
           | stops being used, which leads to use-after-free, double-free
           | and memory leak bugs.
           | 
           | Same goes for classical UI approaches. In classical UI, most
           | pieces of state are kept in at least two places, once in code
           | and at least once in the DOM.
           | 
           | For example, in a shopping cart, the total might appear three
           | times, implicitly in the code (as a function that sums the
           | prices of all the items), once as the label of the "open
           | cart" button in the navbar, and once as text in the "your
           | cart" modal, which that button shows or hides. THe cart may
           | be modifiable from different places, the cart modal itself,
           | product pages, product collection pages, order history (when
           | re-ordering recently purchased items) etc.
           | 
           | In the classical approach, you need to make sure that all
           | modifications to the cart accurately change the state in all
           | three places. You also need to ensure that if you remove a
           | product from the cart using the modal and you're currently on
           | a page that lets you order the product in any way, the
           | "remove from cart" button on that page needs to turn back
           | into "add to cart", and there may be hundreds of different
           | such buttons, which the cart modal needs to handle somehow.
           | It is very easy to make mistakes here and have the state in
           | the code (array of products) fall out of sync with what the
           | user sees on the page.
           | 
           | In React, there's just one array of products, one function to
           | calculate the total, and a lot of places in the code that use
           | this array. WHenever the array changes, the pieces of the
           | page that rely on it automatically re-render, while
           | everything else stays the same. There's no way for the UI and
           | the array to fall out of sync, and there's no need to track
           | where the array is being used and where it's being modified.
        
             | itsgabriel wrote:
             | I don't quite get how this reactivity is only possible with
             | a VDom, for example Svelte
             | https://learn.svelte.dev/tutorial/updating-arrays-and-
             | object... also allows you to update the UI on changes to
             | the array.
        
               | miki123211 wrote:
               | To extend the malloc versus GC metaphor, Svelte here is
               | like Rust, it has really good developer experience while
               | still giving you most benefits of Virtual DOM.
        
         | edflsafoiewq wrote:
         | It enabled a style of view library where you write immediate-
         | mode type code that always recreates a whole component from
         | scratch, versus having to write finicky code that both creates
         | and then updates pieces of the page as state changes (dirty
         | tracking, etc). Behind the scenes, you're creating the vDOM
         | from scratch, which is diffed against the actual retained-mode
         | DOM, and then only the pieces that are different are updated.
        
         | ProofHouse wrote:
         | Slows down your app too, sometimes. Depends how well you can
         | work with and mutate a DOM, but if all things equal no VDOM is
         | always faster cause no diffing.
        
           | ProofHouse wrote:
           | A lot of people can benefit from offsetting mutations with
           | rAF and dbl rAF and batching reads/writes (FastDOM), before
           | needing or considering a VDOM. VDOM came to prominence
           | because of REACT and then started becoming used even when it
           | wasn't needed. It does serve a purpose and scenario when
           | needed, tho
        
         | __s wrote:
         | With vDOM I could say `x = JSX` then cache that in state,
         | inserting it in multiple places. Switching to Solid you have to
         | make sure to use `x = () => JSX` & there's some mental model
         | adjustments since logic outside JSX isn't reactive
        
         | acdha wrote:
         | If you couldn't efficiently batch updates, a vDOM could avoid
         | repetitive updates in close succession, especially on IE6 (the
         | browser React was designed for).
         | 
         | If you can control your app's structure, it primarily adds
         | significant increases in the RAM and CPU required for your app
         | and slows load time because you are using a huge amount of
         | JavaScript to emulate the carefully tuned C++ code built in to
         | the browser. If you notice, most of the benchmarks from when
         | React launched claiming performance wins were compared to
         | heavyweight frameworks or complex jQuery plug-in combinations
         | where a single user interaction might trigger cascading updates
         | forcing the browser to rerender things which didn't change
         | along or to reflow multiple times in cascading update-measure-
         | update chains. Pure DOM implementations were always faster,
         | often by multiple orders of magnitude and once you could drop
         | IE6, and then IE11, the DOM APIs and CSS were rich enough that
         | much of the library code is now a net negative as well (e.g.
         | people used to use complex code trying to build layouts which
         | CSS grids solved).
        
       | config_yml wrote:
       | Reminds me of Action Script 3 which had XML at the core of the
       | language. It was a fun language to work with, but famously failed
       | to become ES4. Oh well, took us 10+ years to arrive close to that
       | with Typescript and JSX.
        
         | quink wrote:
         | https://en.wikipedia.org/wiki/ECMAScript_for_XML - Firefox had
         | it too, but people at large just didn't want it, so it got
         | removed. It got disabled for web pages with the release of
         | Firefox 17, 6 months prior to the first release of React.
        
           | sltkr wrote:
           | Personally I never heard about it. So it might not be that
           | people didn't want it, but that it wasn't promoted much.
           | 
           | Also, it sounds like the only browser to ever support it was
           | Firefox? That was probably much more of a limiting factor for
           | adoption.
        
             | kibibu wrote:
             | If you weren't coding for the flash platform you would have
             | easily missed it.
             | 
             | Its a shame, E4X was really nice
        
           | mhitza wrote:
           | People didn't want it because browsers didn't support it
           | (except FF, as you noted). Some of us had our fingers crossed
           | that other browsers would pick it up.
        
         | shove wrote:
         | I don't recall being able to construct XML inline like this
         | unless maybe that was a Flex server thing?
        
           | dugmartin wrote:
           | It was an extension to ES4 called E4X - it allowed inline xml
           | along with a new xml data type. More info here:
           | https://evertpot.com/ecmascript-4-the-missing-version/
        
           | noduerme wrote:
           | I think parent must be referring to Flex components. AS3
           | itself had an XML library which I recall being absolute hell
           | to work with. The better way to send things over the wire
           | with AS3 was with AMF.
        
             | theturtle32 wrote:
             | Nope. I worked with Flex and it's MXML files extensively.
             | But the parent is talking about E4X, which was an extension
             | to ECMAScript that allowed you to use XML elements inline
             | with JavaScript in a manner VERY similar to how JSX is used
             | today. It also included the ability to much more easily
             | query and otherwise work with those XML document trees in
             | native JavaScript.
        
             | config_yml wrote:
             | No, writing XML was the declarative part of Flex (like
             | HTML), but AS3 had it's own XML type so you could do things
             | like this:
             | 
             | var data:XML = <foo><bar>hello</bar></foo>
             | 
             | and then data was an object instance like you'd expect
        
           | zoogeny wrote:
           | I don't recall being able to do the XML construction inline
           | either, but that just might be my memory.
           | 
           | However, the XML selector syntax was a godsend. Recursively
           | parsing an XML tree is really a pain. E4X would allow you to
           | do things like:                   var foo =
           | someXml..childNodes.@attribute;
           | 
           | I'm not even sure if that would work actually. There were a
           | bunch of operators for doing things like getting a collection
           | of children that all had the same tag so you could work with
           | XML like:                   <someXml>
           | <intermediateNodeYouWantToSkip>                <childNode
           | attribute="1" />                <childNode attribute="2" />
           | <childNode attribute="3" />                <unrelatedNode />
           | </intermediateNodeYouWantToSkip>         </someXml>
           | 
           | Another post here said people didn't want it, but I don't
           | think that was the real reason it was dropped. There was a
           | lot of drama at the time about Flash in general and a massive
           | debacle about EcmaScript 4 (which ActionScript more or less
           | adopted). There was also the whole XHTML thing happening.
           | 
           | Basically JSON as a format won out over XML and ES4/XHTML
           | were ditched. Frankly, a world that revolved around XML/SOAP
           | would have been a nightmare, so I guess killing off the easy
           | processing of XML in JavaScript helped to stave off that
           | potential future. XSS, XSLT and E4X were all casualties.
        
       | waynenilsen wrote:
       | This plays very nicely with the locality of behavior model of
       | htmx
        
       | sophiebits wrote:
       | These examples are cool but I think it's important to note that
       | none of them show components whose props can change over time,
       | since that ability doesn't seem to be modeled at all. Clever if
       | you don't need that but I'm having trouble seeing how it would
       | scale to more complex apps.
        
         | numpad wrote:
         | Maybe I'm missing something, but how would this prevent you
         | from using setTimeout/setInterval? But I agree that these
         | projects often work great in small use cases, but quickly
         | crumble under "real world" scenarios.
        
           | novocantico wrote:
           | I admit that the two most complex "interactive apps" I've
           | built with this are not that complex according to many
           | standards:
           | 
           | * https://www.immaculatalibrary.com/books.html (src = https:/
           | /github.com/sdegutis/immaculatalibrary.com/blob/main/...)
           | 
           | * https://www.immaculatalibrary.com/prayers/ (src = https://g
           | ithub.com/sdegutis/immaculatalibrary.com/blob/main/...)
        
           | _heimdall wrote:
           | I'd be hesitant to run something like a 30fps render loop in
           | a web app. Its been years since I last saw or tried that in a
           | real world app but it didn't end well for performance.
           | 
           | Your best bet would be to queue up specific UI changes that
           | need to be made as diff's rather than checking the entire UI
           | state. At that point, though, you might as well run them
           | immediately as the change is needed.
           | 
           | If that was still a perf problem you would end up chasing a
           | very complex solution like react fiber to partially update
           | the UI on a loop while periodically pausing for user events.
        
           | sophiebits wrote:
           | Sure, if you blow away the entire app on every state change.
           | But that would lose not only state defined in components
           | (like `i` in ClickMe) but also all state implicitly stored in
           | DOM elements (selection, focus, scroll position, input value,
           | media playback).
        
           | throwitaway1123 wrote:
           | I would almost certainly never implement a UI as a render
           | loop, but if you wanted to go down that path
           | requestAnimationFrame is a much more idiomatic way to do it
           | if you want to match the user's display refresh rate.
        
         | hellojebus wrote:
         | I'm by no means an advocate of this library, and never plan to
         | use it, but to support component props that trigger rerenders,
         | a'la React/Vue, I would use JS Proxies here. Wouldn't be that
         | hard to implement.
        
           | sophiebits wrote:
           | How would you suggest using Proxy?
        
         | novocantico wrote:
         | The technique I used here and in all my browser-side code is
         | the exact same technique used by VS Code internally, and it
         | scales very well. The only difference in my code is it's more
         | concise than writing 10 lines to construct and setup a DOM
         | element the typical way.
         | 
         | Honestly, the real interesting part about my framework is
         | _literally everything else_. Returning strings from JSX on the
         | ssg-side; being able to import raw source directories and
         | manipulate string|Buffer at ssg-time; the extremely efficient
         | and lightning fast module system I wrote on top of chokidar and
         | swc; probably more I 'm forgetting, but basically the JSX-as-
         | DOM is only the most _visually_ interesting part. But really
         | just a party trick.
         | 
         | [edit] Case in point: the source code to vanillajsx.com is
         | extremely concise and clear and short, I literally wrote the
         | whole thing today with zero deps (besides imlib), and the JSX-
         | as-DOM demos are the least innovative part of it:
         | https://github.com/sdegutis/vanillajsx.com/tree/main/site
        
           | novocantico wrote:
           | I just added a more complex todo app to the bottom of the
           | page. So it should give an idea of how a more complex
           | hierarchy can respond to events elsewhere in the hierarchy
           | and update themselves and each other accordingly.
        
         | tombl wrote:
         | Yup, in order to scale this approach to any real size (and
         | still have confidence that everything is working together like
         | you expect), a proper reactivity solution is needed.
         | 
         | For those that appreciate this approach of JSX returning
         | concrete DOM elements, Solid works exactly like this, with the
         | addition of a proper reactivity layer.
        
       | ibash wrote:
       | People forget what problem the virtual dom and react is supposed
       | to solve.
       | 
       | No better article than this:
       | https://blog.vjeux.com/2013/javascript/react-performance.htm...
        
         | Spivak wrote:
         | And then Svelte showed that you could avoid all that with a
         | compilation step and live update the dom efficiently.
         | 
         | https://svelte.dev/blog/virtual-dom-is-pure-overhead
         | 
         | React is also at the point where re-rendering the whole app is
         | a fiction the library maintains for you while being smarter and
         | doing less, why not go the whole way?
        
           | ibash wrote:
           | Agree, react is way too bloated right now. The original idea
           | and first versions were great.
        
             | culi wrote:
             | The original idea and first versions were extremely
             | inefficient and unscalable
        
           | Aeolun wrote:
           | And then SolidJS showed that you could do the same thing even
           | without a compilation step.
        
         | guax wrote:
         | For me is because is hard to remember that problem while
         | dealing the the ones react brings.
        
         | insane_dreamer wrote:
         | There are plenty of cases where optimizing for performance
         | isn't necessary. This is where React is not worth the extra
         | headache and complexity.
        
           | presentation wrote:
           | React is set to become much less complex as a user once the
           | react compiler is in place and if you use server
           | components/actions; in my product we've already basically
           | eliminated 95% of useEffect calls, almost all data fetching,
           | client side state management with the current gen tools, and
           | once the compiler is in then all memoization will be gone
           | too.
           | 
           | You still end up with the bloated bundle size but with one of
           | the more modern react alternatives you can eliminate that
           | too. So at least for me, I don't mind the build complexity
           | for the power I get; especially now that node itself is
           | supporting typescript, the build side is getting simpler to
           | set up as well.
        
         | mbivert wrote:
         | (honest question, not trying to be snarky) Do you have one
         | (many would be great) use cases where the practical gain of the
         | virtual DOM solutions have a genuine impact?
         | 
         | I'm asking because, many of React (or friends) introductory
         | material naturally focus on building things like TODO lists or
         | Tic Tac Toe; while those offer insights into how to work with
         | React (& cie), they're not showcasing cases where the
         | performance gains are perceptible, and IMO not even cases where
         | the "organizational" benefits of such libraries are salient.
        
           | eterps wrote:
           | This question is crucial to understanding the true value of
           | React and virtual DOM technologies.
           | 
           | While there's no doubt that React and virtual DOM offer
           | advantages, it's essential to clearly demonstrate where and
           | how these benefits manifest in real-world applications.
           | 
           | > _they 're not showcasing cases where the performance gains
           | are perceptible_
           | 
           | According to this commenter, it's not even about the
           | performance gains:
           | 
           | https://news.ycombinator.com/item?id=41271272
           | 
           | > _and IMO not even cases where the "organizational" benefits
           | of such libraries are salient_
           | 
           | Apparently, that is what it ultimately boils down to:
           | 
           | https://news.ycombinator.com/item?id=41271367
        
             | mbivert wrote:
             | > _While there 's no doubt that React and virtual DOM offer
             | advantages, it's essential to clearly demonstrate where and
             | how these benefits manifest in real-world applications._
             | 
             | Definitely; it's a struggle to find precise, concrete
             | arguments in this direction. And there are many good
             | reasons to be conservative: e.g. inheritance-based OO was
             | sold with "VW inherits Car"; looks great on paper, but not
             | as much in front of real-world issues.
             | 
             | > _Apparently, that is what it ultimately boils down to:_
             | 
             | If so, I'd be left wondering how much of this is actually
             | caused by a lack of discipline, as seems to be for example
             | indicated by the "dumb reflows" issues.
        
           | NohatCoder wrote:
           | Obviously this always depends on what code you compare it to.
           | I don't think there can be much doubt that a well written
           | performance oriented framework-free implementation is in
           | practice always going to be faster than anything using
           | virtual DOM, as one can update simply the parts that need
           | updating without creating the virtual DOM in the first place.
           | 
           | If you assume programmers who don't know what they are doing
           | it is a very different question. Some people will manage to
           | make a train wreck both with and without a framework. But if
           | we assume that there is a skill level where people will
           | manage to make something useful with a framework, but not
           | without it, or vice versa, then I really do not know which
           | way it swings.
        
           | ibash wrote:
           | Yes:
           | 
           | One project I worked on was a BI tool with a fair amount of
           | complex state. Before we introduced react we were using
           | backbone, event listeners, and managing dom state ourselves.
           | With react we made it declarative, which simplified things.
           | 
           | Another project was an email client with a lot of complex
           | state and caching. That started with and continued to use
           | react so I don't have a direct performance comparison. But
           | again, managing the state manual would have been a nightmare.
        
       | cribbles wrote:
       | These "what ifs" are kinda funny because the origins of JSX can
       | be traced back to Facebook's XHP[1], which took explicit
       | inspiration from E4X[2], an early JS standard that looked and
       | behaved similar to the library described here.
       | 
       | [1] https://engineering.fb.com/2010/02/09/developer-
       | tools/xhp-a-...
       | 
       | [2] https://en.m.wikipedia.org/wiki/ECMAScript_for_XML
        
         | spankalee wrote:
         | E4X had the unfortunate downside of returning actual DOM
         | instances, which needed to be updated imperatively. That's why
         | JSX eclipsed it, and there hasn't been a serious proposal for
         | HTML templating in JS since then.
         | 
         | But maybe we can revive the general idea with a modern take:
         | https://github.com/WICG/webcomponents/issues/1069
        
           | lolinder wrote:
           | > had the unfortunate downside of returning actual DOM
           | instances, which needed to be updated imperatively.
           | 
           | Isn't this what we have in TFA?
        
             | bastawhiz wrote:
             | Yes, for elements. The project here also supports a notion
             | of components, though, which E4X didn't contemplate.
        
           | olliej wrote:
           | Also E4X was only ever implemented in Firefox, never really
           | got traction even in Firefox.
           | 
           | But even considering the single implementation problem, it
           | also was just not a good language model, nor was it well
           | specified or defined and it brought with it a pile of weird
           | baggage and complexity.
           | 
           | Then because it was The Future there was no real thought into
           | proper interop with JS (it was essentially a completely
           | independent spec so adopted general syntax but specified in a
           | way that meant JS could not simply adopt that syntax).
        
           | kreetx wrote:
           | With "imperatively" you mean that the user of the templating
           | system has to do it imperatively, and that is bad? Asking
           | because imperative updates seem to be the way to go within
           | the implementation, instead of creating new instances of
           | elements every time.
        
           | Sephr wrote:
           | > E4X had the unfortunate downside of returning actual DOM
           | instances, which needed to be updated imperatively
           | 
           | Firefox never shipped the optional E4X DOM APIs. I wrote a
           | polyfill for them at the time.[1]
           | 
           | 1. https://github.com/eligrey/e4x.js/blob/master/e4x.js
        
           | SkiFire13 wrote:
           | > which needed to be updated imperatively
           | 
           | VanillaJSX seems to suffer from the same problem though.
        
           | megaman821 wrote:
           | There are separate proposals from web components that get rid
           | of imperative updates.
           | https://eisenbergeffect.medium.com/the-future-of-native-
           | html...
        
         | olliej wrote:
         | Fun fact, E4X is the reason JavaScript has 'for(of)' instead of
         | 'for each' (the reason we didn't get 'for (:)' is even dumber -
         | it would conflict with ':type' annotations a few TC39 members
         | were convinced would magically be in the language)
        
           | rlt wrote:
           | Like the type annotations that are now in TypeScript?
        
             | olliej wrote:
             | Yup, that were in typescript, pascal (and rust, etc when
             | they came out).
             | 
             | But there was no real progress after years of them pushing
             | this syntax, but failing to actually define a type system
             | that was coherent, or a model that would allow it.
             | 
             | As a result I proposed `for (of)` largely to prevent sane
             | enumeration from being blocked on the intransigence of two
             | people.
             | 
             | It's also worth noting that for(:) enumeration would not
             | even preclude their syntax - it's certainly not
             | grammatically ambiguous - and most real world code in
             | languages that support enumeration directly and support
             | inference doesn't explicitly specify the types , so the
             | ugliness of `for(let a:type:expression)` would have be rare
             | anyway.
             | 
             |  _shrug_
             | 
             | Given that ECMA literally killed E4X a few years later the
             | blanket ban on "for each" or "foreach" (because it would be
             | "confusing" in E4X) is arguably worth than for(:), but
             | again _shrug_
        
           | IshKebab wrote:
           | There is a proposal to add them, though it does seem to be
           | stalled.
        
             | olliej wrote:
             | There were proposals almost 2 decades ago. They've never
             | gone anywhere because proponents of type specifiers don't
             | want to do the necessary corollary: specifying the type
             | system.
             | 
             | Typescript and similar can do it because they don't have to
             | specify the type system, and can't change it in meaningful
             | ways over time. Things in the language standard cannot be
             | easily changed, if they can be changed at all.
        
               | IshKebab wrote:
               | > the necessary corollary: specifying the type system.
               | 
               | It's clearly not _strictly_ necessary though. Python has
               | shown that.
               | 
               | I mean I agree it is pretty mad to just say "you can
               | write types but they mean whatever" but surprisingly in
               | practice it seems to work ok.
        
       | spullara wrote:
       | I was bummed when they removed E4X from the browser
       | implementations.
        
       | novocantico wrote:
       | Thanks for taking some interest in my project. It came from being
       | frustrated with the state of SSGs over the past 10 years. I
       | mostly just make static websites, and I wanted something that was
       | simple and intuitive to me, and JSX seemed like a great fit. But
       | I got very tired of the disproportionately scaled complexity of
       | JSX frameworks like React. Long story short, I made an SSG that
       | just renders JSX as strings. It was natural to extend that to the
       | browser to just render JSX as DOM elements. And in a few cases
       | (mostly layout) it lends well to shared components. Overall I'm
       | happy with what I came up with, although some of it is admittedly
       | a little hacky, and IDE support isn't as good as it could be.
       | 
       | [edit] Oh also, this solution works really well for SEO. That's
       | another problem I didn't find solved well in other JSX
       | frameworks.
        
         | thelastinuit wrote:
         | not the hero we deserve but the villain we need
        
         | hyperhello wrote:
         | What I'm seeing here is not new. It's this vanilla pattern but
         | with enough back support to leave off the framing and get the
         | syntax highlighting:
         | 
         | Var button = html('<button>im a button</button>');
         | 
         | The html() function is trivial, but it just doesn't _feel_ like
         | real programming to do this, even though there's nothing else
         | to it in the end.
        
           | hyperhello wrote:
           | Downvote me but tell me why. The example is using .onclick,
           | .textContent, etc in a completely vanilla way. I'm just
           | pointing out you can get all the way vanilla and it still
           | works. What's the issue?
        
             | novocantico wrote:
             | lolinder explained it well in here
        
               | hyperhello wrote:
               | He did, and he pointed out the point is just IDE support
               | so it has typing and autocomplete and syntax
               | highlighting. Thanks, we agree!
        
           | mock-possum wrote:
           | Tagged template literals for html view templating is what I
           | LOVE about Lit and lit-html. It's JavaScript you can run
           | natively in browser, no server or pre processor/build step
           | necessary.
        
         | fredmerc wrote:
         | A JSX for Django server side would be cool.
        
           | WesleyJohnson wrote:
           | How would you envision this working?
        
           | megaman821 wrote:
           | Not exactly JSX, but I came across a package django-
           | cotton[https://github.com/wrabit/django-cotton], that is html
           | syntax first components.
        
         | shepherdjerred wrote:
         | Just curious, have you seen Astro? I feel like it's the perfect
         | SSG, but maybe you have some reservations that VanillaJSX
         | solves.
        
           | newzisforsukas wrote:
           | astro is nearly, if not as, "complex" as react, no?
        
             | molszanski wrote:
             | As person who has been doing "react" since 2016 I would say
             | that it removes so much of the "react" complex BS that I am
             | surprised it is not x100 times more popular.
             | 
             | We've recently moved one service from next to Astro and it
             | was just removing a ton of boilerplate and "dance around"
             | code.
        
               | FractalHQ wrote:
               | That's how I felt going from Astro to Sveltekit, but
               | that's a shorter distance to travel.
        
               | molszanski wrote:
               | Oh, but you are moving out of React. And svelto IMO is
               | waaay friendlier and "sane" than "typical" react. Svelte
               | reactive model (observables and computed) are very
               | friendly and simple to use.
        
             | shepherdjerred wrote:
             | It doesn't really make sense to compare React to a static
             | site generator.
        
           | _heimdall wrote:
           | I'm a big fan of Astro, though I could see it being a bit
           | more of an adjustment for JSX users than Svelte users since
           | Astro's syntax was originally based on Svelte.
           | 
           | That said, JSX can be used easily with Astro as long as you
           | get used to at least a bit of The `.astro` syntax for wrapper
           | components and pages/layouts.
        
           | vips7L wrote:
           | SSG?
        
             | blackeyeblitzar wrote:
             | Static site generator, apparently
        
           | novocantico wrote:
           | For all "have you tried ___" questions, the answer is the
           | same. I've been trying all these new techs for the past 10-15
           | years, regularly, as soon as they come out, for the first few
           | years with much with excitement, and later with
           | disillusionment and less regularity.
           | 
           | Another user below said
           | 
           | > We've recently moved one service from next to Astro and it
           | was just removing a ton of boilerplate and 'dance around'
           | code.
           | 
           | And I get why it happens. When you first try out a new
           | framework, you _allow_ yourself to learn and add its inherent
           | complexity, _knowingly and intentionally_. You say to
           | yourself,  "it's part of the dream, it's going to work out;
           | there's a vision, just trust the process." This is true with
           | literally all frameworks.
           | 
           | But they never deliver. The complexity is never worth it, and
           | in the end, the intentionally added complexity is always
           | intentionally and gladly removed when it becomes clear that
           | it was _unnecessary_ complexity. This is what I am glad to
           | have learned so thoroughly that I no longer try to learn new
           | frameworks when I initially see its complexity, imagine
           | adopting it in view of my experience, and recognize that its
           | almost always not worth it.
           | 
           | Look at the code on vanillajsx.com. Besides JSX and types,
           | it's plain JavaScript and DOM manipulation. Translating it to
           | document.createElement would add almost no lines of code.
           | There's no unnecessary complexity. That's the whole point of
           | the site. The simplicity of discovering and removing
           | unnecessary complexity is wonderful and refreshing, and I
           | think a lot of people agree.
        
             | dimal wrote:
             | I like your thinking. Things have gotten far more complex
             | than they need to be. We've been piling abstractions on top
             | of abstractions for too long and there needs to be a
             | culling. If we get rid something that we really did need,
             | that's better than the alternative. It's best now to ditch
             | it all and see what we really need.
        
             | samtheprogram wrote:
             | So, I take it you haven't tried Astro then?
        
             | shepherdjerred wrote:
             | I think you're misunderstanding the poster you quoted.
             | They're indicating a positive experience with Astro.
             | 
             | > We've recently moved one service from next to Astro and
             | it was just removing a ton of boilerplate and 'dance
             | around' code.
             | 
             | ---
             | 
             | > And I get why it happens. When you first try out a new
             | framework, you allow yourself to learn and add its inherent
             | complexity, knowingly and intentionally. You say to
             | yourself, "it's part of the dream, it's going to work out;
             | there's a vision, just trust the process." This is true
             | with literally all frameworks.
             | 
             | I am quite picky and have strong opinions. I've used Astro
             | for more than a year and still love it. There is complexity
             | (especially if you use SSR), but for the use case of "I
             | just want a static site" it is wonderful.
             | 
             | > Look at the code on vanillajsx.com. Besides JSX and
             | types, it's plain JavaScript and DOM manipulation.
             | Translating it to document.createElement would add almost
             | no lines of code. There's no unnecessary complexity. That's
             | the whole point of the site. The simplicity of discovering
             | and removing unnecessary complexity is wonderful and
             | refreshing, and I think a lot of people agree.
             | 
             | I don't disagree, but this doesn't replace what you might
             | want for SSG. For one, this requires JS on the client.
             | Astro compiles to static HTML despite using JSX-like
             | syntax.
             | 
             | As an example, here's my Astro site and source code:
             | 
             | * https://sjer.red/
             | 
             | * https://github.com/shepherdjerred/sjer.red
        
               | novocantico wrote:
               | My framework (imlib[1]) is actually more of a framework
               | akin to Astro than what's showcased on vanillajsx.com,
               | which itself is built with imlib.
               | 
               | It just runs your code in a node.js process, and
               | translates your JSX expressions into jsx() calls. On the
               | node.js side[2], jsx() returns a string from its
               | tag/attrs/children. On the browser side[3], jsx() returns
               | DOM elements.
               | 
               | Combined with a little bit of architecture, it becomes
               | something extremely well suited to creating static sites.
               | I guess SSG is an outdated term now, maybe it's a
               | framework? Or a platform?
               | 
               | In any case, it seems to do something similar to Astro,
               | but in a significantly simpler way. The only "bundle" it
               | needs in the browser is /@imlib/jsx-browser.js [4] which
               | in itself is just jsx-dom.ts (its impl is overridable by
               | the "framework" user). And on the node.js side, it's
               | implemented as a very small "vm" of sorts [5].
               | 
               | I'm not against Astro, I just get all the same benefit
               | people here are saying Astro has, but with orders of
               | magnitude more simplicity imo.
               | 
               | I've used imlib to make a relatively large website [6],
               | in fact imlib was developed as this website and extracted
               | from it over the past year. I have absolutely no
               | difficulty breaking down my site into various reusable
               | and encapsulated JSX components, both on the ssg-side and
               | the browser-side. Development time is lightning fast. IDE
               | support is essentially automatic. The site loads
               | instantaneously in the static parts, and as quickly as
               | reasonable in the dynamic parts.
               | 
               | [1] https://github.com/sdegutis/imlib
               | 
               | [2] https://github.com/sdegutis/imlib/blob/main/src/jsx-
               | strings....
               | 
               | [3] https://github.com/sdegutis/imlib/blob/main/src/jsx-
               | dom.ts
               | 
               | [4] https://vanillajsx.com/@imlib/jsx-browser.js
               | 
               | [5] https://github.com/sdegutis/imlib/blob/main/src/runti
               | me.ts
               | 
               | [6] https://github.com/sdegutis/immaculatalibrary.com
        
               | shepherdjerred wrote:
               | Thanks for taking the time to clarify & not getting
               | hostile :)
               | 
               | I'll look into imlib a little more.
        
         | todotask wrote:
         | Large WASM payload on your site could be optimized.
        
         | AltruisticGapHN wrote:
         | Have you looked into lit-html?
         | 
         | Coming from Vue I was really surprised it does a lot of what
         | Vue templating does, including attaching events, with just
         | vanilla JS templates. And when you use VSCode lit extension,
         | you get syntax highlighting and full type checking inside the
         | templates.
         | 
         | I learned about lit-html after a tweet from Marc Grabanski,
         | where he said he used lit-html with vanillajs, not Lit.
         | 
         | After some experimenting I found it works great and it seems
         | like you are trying to solve something very similar.
         | 
         | When you use the lit-html template package you can do basically
         | evetything that is described in the Templates chapter
         | 
         | https://lit.dev/docs/templates/overview/
         | 
         | ... without all the other abstraction of components that are
         | part of lit-element.
         | 
         | https://lit.dev/docs/libraries/standalone-templates/#renderi...
        
         | dimal wrote:
         | Love the idea. FYI, on your demo page, the todo app is 404. And
         | you might want to spell out static site generator instead of
         | saying "SSG" on your docs. I didn't know what SSG was, even
         | though I've used static site generators. I had to ask the AI.
        
       | nashashmi wrote:
       | I wonder what The examples would look like in ECMAscript 5.
        
       | spankalee wrote:
       | Returning actual DOM nodes entirely blunts the big advantage of
       | JSX (and non-JSX libraries like Lit) - which is their immediate
       | mode style API, and UI=f(state) model.
       | 
       | You want to return a description of the DOM, rather than the real
       | DOM, because you want to be able to reevaluate your templates
       | repeatedly with new state, and efficiently update the DOM where
       | that template is rendered to.
       | 
       | All the examples here use imperative DOM APIs to do updates, like
       | with this:                   function TodoInput(attrs: { add: (v:
       | string) => void }) {           const input = <input /> as
       | HTMLInputElement;           input.placeholder = 'Add todo
       | item...';           input.onkeydown = (e) => {             if
       | (e.key === 'Enter') {               attrs.add(input.value);
       | input.value = '';             }           };           return
       | input;         }              class TodoList {           ul = <ul
       | class='todolist' /> as HTMLUListElement;           add(v: string)
       | {             const item = <li>{v}</li> as HTMLLIElement;
       | item.onclick = () => item.remove();
       | this.ul.append(item);           }         }
       | 
       | Avoiding those `input.onkeydown = ...` and `this.ul.append(item)`
       | cases, and instead just iterating over items in your template, is
       | probably the main benefit of a VDOM.
       | 
       | (The problem with VDOMs is that diffing is slow, a problem solved
       | by using templates that separate static from dynamic parts, like
       | Lit - a library I work on).
        
         | recursive wrote:
         | > You want to return a description of the DOM, rather than the
         | real DOM, because you want to be able to reevaluate your
         | templates repeatedly with new state, and efficiently update the
         | DOM where that template is rendered to.
         | 
         | Depends who "you" are. I prefer to have my DOM nodes updated in
         | place without all the reconciliation machinery. (no implication
         | about what _you_ want)
        
           | spankalee wrote:
           | You don't need diffing or reconciliation to turn a
           | description of DOM into DOM. Lit works without a VDOM.
           | 
           | If all JSX does is return a DocumentFragment that you then
           | need to imperatively add event listeners to and imperatively
           | update, how is it much better than innerHTML?
        
             | lolinder wrote:
             | 1) Type safety for element props.
             | 
             | 2) Autocomplete for element props.
             | 
             | 3) IDE support such as refactors and jump to
             | definition/jump to usages.
             | 
             | 4) Proper syntax highlighting out of the box instead of the
             | editor just saying "there's a string here".
             | 
             | 5) A uniform pattern for defining custom components that
             | work the same as primitives, rather than defining custom
             | components as helper functions returning string fragments
             | or something like that.
             | 
             | And so on. JSX has a lot going for it regardless of the
             | semantics chosen. It's just a syntax that is very
             | convenient for lots of kinds of tooling, and it's
             | completely unopinated about the semantic context in which
             | it is used.
        
               | _heimdall wrote:
               | These are definitely helpful, but what you are describing
               | are all language tool features rather than features of
               | JSX itself. 5 would be the exception, but that is just
               | user preference of what kind of syntax one likes to write
               | components with.
        
               | lolinder wrote:
               | Well, yes. But OP was asking about what makes this better
               | than `innerHTML`, and the obvious answer is that support
               | for HTML programming embedded in JavaScript strings is
               | generally bad while support for JSX is _very_ good across
               | all editors.
        
             | recursive wrote:
             | You can have JSX that produces DOM nodes or "light-weight
             | element descriptions".
             | 
             | You can have imperative event listeners and updates.
             | 
             | These are two independent dimensions. I made UI framework
             | called mutraction that produces real DOM elements from JSX
             | expressions. It also updates any contents or attributes of
             | those DOM nodes based on their dependencies without
             | requiring imperative DOM interaction from application code.
             | 
             | https://github.com/tomtheisen/mutraction
             | 
             | Here's a click counter. `track()`, as you might guess
             | creates a proxy so that reads and writes can be converted
             | into dependencies.                   const model = track({
             | clicks: 0});         const app = (             <button
             | onclick={() => ++model.clicks }>                 {
             | model.clicks } clicks             </button>         );
             | document.body.append(app);
        
             | esprehn wrote:
             | I think the answer to that is probably "as good as soy, but
             | with modern ergonomics". E4X was basically this and I think
             | it's a much nicer way to build DOM trees than strings since
             | you can't create invalid markup or concat partial tags. It
             | also lets you reuse subtrees naturally where innerHTML
             | makes that impossible.
        
             | Izkata wrote:
             | innerHTML loses all local state, such as which elements
             | have focus or where the cursor is in a text field. Back
             | when React first came out and people were getting used to
             | the idea of VDOM diffing, they had demos front and center
             | about how by using those diffs to only change what needed
             | to change, such local state wouldn't be lost.
             | 
             | This in theory could do something to copy that local state
             | over, or diff the two DOMs directly without a VDOM (though
             | from the sound of it, it probably doesn't).
        
           | ericmcer wrote:
           | If you work on a team of suitable size I would hesitate to
           | not leverage a VDom. I trust myself to not trigger dumb
           | reflows, but the way I see a lot of people using React this
           | could be a perf nightmare.
        
             | acdha wrote:
             | I think that hits the real problem: it's staffing and
             | culture, not the tool. The 90th percentile site using a
             | vDOM is also a perf nightmare, especially for anyone who
             | doesn't have a recent Apple device on a fast network, and
             | that often has big impacts on usability and accessibility
             | as well (dynamic loading sucks on screen readers unless you
             | put way more time into it that most people do).
             | 
             | I was painfully reminded of that while visiting Europe last
             | month on a data plan which was clearly deprioritized on
             | partner networks - the old sites with .php in the URLs
             | loaded in a few seconds and worked perfectly, but every
             | time something failed to load in less than 5 minutes or
             | partially loaded but didn't work a quick trip over to
             | webpagetest.org showed a lot of NextJS, React, et al.
             | scripts trickling in because clearly a form with half a
             | dozen fields needs 25MB of JavaScript.
             | 
             | The root cause is obvious: you get what you measure. If
             | businesses prioritize Jira tickets closed per day, they're
             | going to get this soup of things promising to be easy to
             | use for high developer velocity and they're never going to
             | get around to the optimizing it. If they're trying to be
             | able to hire as cheaply as possible, they're going to look
             | for the current tool boot camps are pushing and hire based
             | on that, not looking for deeper knowledge of web standards
             | or experience which costs more and shrink the candidate
             | pool. If they're looking for a safe choice, Facebook's
             | marketing means all of the big consulting companies will
             | push React and few people will pause long enough to ask
             | whether they're building the same kind of apps it was
             | designed to build (long session times, tons of local state
             | being mutated, etc.) or whether they're willing to invest
             | the time needed to get it to perform reliably and well.
        
             | MrJohz wrote:
             | There are more and more frameworks that avoid the VDOM but
             | still resolve this fine. As long as DOM mutation is handled
             | by the framework (and not done ad-hoc), and as long as the
             | framework has a mechanism for deferring those mutations
             | until after all reads, then there shouldn't be a problem.
             | This is the approach taken by SolidJS, Svelte, and even the
             | new rendering model for VueJS.
             | 
             | In all these frameworks, mutations happen inside effects,
             | and effects are scheduled such that they all happen at the
             | end of the tick, avoiding reflows and thrashing.
        
         | JasonSage wrote:
         | I agree with the sibling comment that this really depends on
         | the user. To take a different approach: JSX is just a different
         | DSL to the createElement function call pattern (see Preact.h
         | for example) and all of the benefits you're describing come
         | from the framework and runtime.
         | 
         | More concisely: JSX is just an alternate function call syntax
         | with some useful applications.
         | 
         | For example at my last company we used JSX to make test data
         | factories that had an XML-like look but were using a builder-
         | pattern in the element creation that was able to make
         | contextual decisions about what was in the final data. Nothing
         | to do with React, DOM, or inability to express the same thing
         | declaratively without JSX.
        
           | spoonfeeder006 wrote:
           | > For example at my last company we used JSX to make test
           | data factories
           | 
           | Thats really interesting, can you elaborate more?
           | 
           | For example did you use a specific JSX compiler? Was that
           | written in house or used a 3rd party library?
        
         | LAC-Tech wrote:
         | _Returning actual DOM nodes entirely blunts the big advantage
         | of JSX (and non-JSX libraries like Lit) - which is their
         | immediate mode style API, and UI=f(state) model._
         | 
         | I feel like this is one of the leakiest abstractions in all of
         | computing. There's a reason there's an entire cottage industry
         | around react; how to stop things rendering multiple times,
         | refreshing needlessly, etc.
        
           | littlestymaar wrote:
           | Yeah, as much as I liked the idea of an "immediate mode API
           | which is in fact retained under the hood which makes things
           | both ergonomic and performant", the reality is that React
           | failed to deliver on that and every sufficiently big app ends
           | up having performance problems that are then fixed by opting
           | out of the immediate mode illusion.
        
         | austin-cheney wrote:
         | Whether you like this project or not, your comment so
         | completely misses the point. You are confusing the JSX syntax,
         | which is what the author wanted by extracting it away from
         | React, for all the React candy. This is a missing the forest
         | for the trees kind of thing.
         | 
         | This mind numbing reliance upon layers of abstraction nonsense
         | around state management is why I really don't like React. State
         | management is ridiculously simple. State management, when done
         | correctly, is the most primitive example of MVC with no
         | abstractions needed.
        
           | SkiFire13 wrote:
           | State management is not simple. You have to constantly keep
           | in sync two different piece of states (your data model and
           | the UI). Making sure that when you modify some parts of your
           | model then everything depending on that is also updated is
           | one of the hardest things to guarantee. Fundamentally this is
           | because it is non-local: you cannot tell what will change by
           | just looking at the definition of what you're mutating.
           | 
           | You might be able to handle this while you're alone and you
           | know everything about your codebase, but the moment you're
           | working with someone else or in a team this will no longer be
           | the case.
        
         | novocantico wrote:
         | > is probably the main benefit of a VDOM
         | 
         | I get the "no more imperative updates" dream. I've used these
         | frameworks for probably a decade. I've mastered them.
         | 
         | Me personally, I prefer imperatively updating my DOM. I get
         | completely fine-grained control over what's happening. I can
         | architect it to be an extremely efficient machine. I can make
         | it extremely easy to add/change/remove/fix features in my apps
         | without forcing myself to think according to anyone else's
         | opinionated methodology.
        
           | nine_k wrote:
           | If you have little state, or simple uniform state, you can
           | actually store it in the real DOM efficiently, as values of
           | controls, or lists of similar DOM nodes under a common known
           | parent. If most of your DOM is static, and you only need
           | small bits of interactivity, React is an excessively heavy
           | tool.
           | 
           | The farther you get into complex GUI territory, the more you
           | want a declarative, functional approach, because it makes
           | things simpler. The closer you are to a handful of controls
           | with simple logic, the more you want to just imperatively
           | tell them what to do, and leave the rest of the page alone,
           | because it makes things simpler. We now just have better
           | tools than jQuery for that.
        
           | newzisforsukas wrote:
           | there is no reason something imperative cannot be
           | declarative. the war is one of style, not capability, so
           | saying you gain "fine-grained control" is kind of
           | meaningless, imo
        
         | francasso wrote:
         | From my experience creating complex web UIs, the performance
         | angle of using a vdom is pure fantasy if your application is
         | complex enough.
         | 
         | In fact I now strongly believe it's counter productive, because
         | most people come to it thinking "I can just trigger however
         | many re-renders of this large piece of UI as I like, the vdom
         | makes it ok" and it doesn't, the performance sucks, but now you
         | have architected the app in a way that requires a rewrite to
         | make the app perform well.
         | 
         | I have seen this exact sequence of events four times, by four
         | different teams. The second, third and fourth, as a principal
         | architect consulting for the team I tried to intervene and
         | advocate for a vanilla architecture that is mindful about
         | performance, citing the issues they would likely experience
         | with react, but to no avail. There was a lot of "oh but there
         | many ways to avoid those issues" followed by a list of things I
         | was presumably ignorant about.
         | 
         | I guess most of us need to learn things the hard way.
        
           | kristiandupont wrote:
           | And from _my_ experience building complex web UIs, those team
           | members were right -- there are many ways to avoid the issues
           | and using vdom is great in general. True, there are
           | situations where it falls short, which is why you will want
           | to fall back to other techniques for those bits of
           | architecture. Just like your JS, Python or Ruby server will
           | call a bunch of functions written in C or the like. That
           | doesn 't mean you should write your entire backend in C.
        
             | littlestymaar wrote:
             | Yes, there are ways to avoid the issues, and they involve
             | abandoning the immediate mode illusion that react created
             | in the name of simplicity.
        
               | johnfn wrote:
               | Write it in React, and if you run into performance
               | issues, there are a bunch of well-known performance
               | optimizations you can make which are easy to discover.
               | It's a well-trodden path that many engineers have walked
               | before.
               | 
               | Write it in your own vanilla framework, and you will
               | effectively re-invent all the complexity of React, but in
               | a way that no one has ever done before. It's easy at
               | small application scales, but once your app gets large,
               | good luck debugging the thing that exists primarily in
               | your principal engineer's head.
        
           | unconed wrote:
           | Yes and the solution is to put on your big boy pants and to
           | actually do your front-end application architecture properly.
           | 
           | Separate source of truth from derived data. Separate possibly
           | valid user intent from validated state. Use contexts to
           | organize the data dependency graph of your application.
           | Ensure all your widgets use a consistent value type in and
           | out, don't let events contaminate it. Use something like
           | cursors or optics to simplify mutations and derive setters
           | automatically.
           | 
           | I've never had an easier time building very complex UI
           | functionality than with React. But it requires you to
           | actively start reasoning about change in your code (what
           | doesn't change), and this is something most people are not
           | used to.
           | 
           | Personally I think React compiler is folly for this reason:
           | they are taking the most interesting part of React, the part
           | that lets you write apps that are incremental from top to
           | bottom, and telling you it's too complicated for you to think
           | about. Nonsense.
           | 
           | The issue is just that React makes pros feel like idiots
           | unless they eat some humble pie and grok the principles and
           | the reasons behind it. Which is that React is what you get
           | when you try to come up with a UI architecture that can make
           | entire classes of problems go away.
           | 
           | Without a VDOM, one way data flow, and diffing, your UI won't
           | just be slow, it'll be full of secret O(n^2) cascades, random
           | ifs to stop infinite cycles, random "let's update this state
           | early so other code can immediately use it" ordering issues,
           | and so on.
        
             | kitkat_new wrote:
             | > I've never had an easier time building very complex UI
             | functionality than with React.
             | 
             | How many frameworks did you have experience with?
             | 
             | > Without a VDOM, one way data flow, and diffing
             | 
             | you wanted to write "or" not "and", didn't you?
        
             | darepublic wrote:
             | > Without a VDOM, one way data flow, and diffing, your UI
             | won't just be slow, it'll be full of secret O(n^2)
             | cascades, random ifs to stop infinite cycles, random "let's
             | update this state early so other code can immediately use
             | it" ordering issues, and so on.
             | 
             | you can adhere to the same principles (one way data flow)
             | without vdom. Not saying it's easy at large scale but it's
             | possible. I don't appreciate people invoking fud towards
             | anyone opting out of their tech choice.
        
           | kitkat_new wrote:
           | you shouldn't project from react to vdom in general:
           | 
           | https://dioxuslabs.com/blog/templates-diffing
        
           | novocantico wrote:
           | There were two groups I was hoping vanillajsx would resonate
           | with. The first is people who still buy into the React dream
           | but are beginning to be disillusioned with its inability to
           | deliver on its promises, and the second is people who already
           | are fully disillusioned.
           | 
           | Specifically, I'm hoping to show that vanilla architectures
           | can be not only performant, but easy to maintain with well
           | designed code that uses stable and known patterns. Using JSX
           | just so happens to clean up the code nicely and make the
           | relationship between React and vanilla very visible, but
           | that's really all it did here.
           | 
           | Although to be fair, the hack required to get JSX-as-DOM to
           | work is really unfortunately and I'm not very happy with it,
           | and I would prefer JSX to just render as an object tree that
           | anyone can render however they want. But when I tried that
           | for a few months or a year, it was not nearly as performant
           | as rendering them as strings as soon as they're evaluated,
           | which can then be cached via standard module caching. At
           | least, that's how I got immaculatalibrary to entirely render
           | all HTML files in ~700ms initially and ~70ms on most file
           | changes.
           | 
           | I'll try to do some experimentation next week to see if I can
           | get more performance back out of having <foo
           | bar={qux}>child</foo> to render as {foo:{bar:qux,
           | children:[child]}} again though, because that would
           | absolutely be the ideal, and would unfork JSX in the same way
           | Typed Annotations proposes to unfork JavaScript types.
        
             | Joeri wrote:
             | Thank you for posting this! VanillaJSX is refreshingly
             | different, and we desperately need new ideas in the front-
             | end space to reduce the complexity and get closer to the
             | browser. I also feel like the discussion in this thread is
             | very rich and gives people on both sides of the fence a lot
             | of stuff to think about.
             | 
             |  _There were two groups I was hoping vanillajsx would
             | resonate with. The first is people who still buy into the
             | React dream but are beginning to be disillusioned with its
             | inability to deliver on its promises, and the second is
             | people who already are fully disillusioned._
             | 
             | I don't know if you've seen it, but Alex Russell just did a
             | blog series where he directly talks about this disillusion
             | and proposes a move away from React for most web apps:
             | https://infrequently.org/series/reckoning/
             | 
             | I am not as anti-React as that myself, but I do agree it is
             | hard to scale up and have it perform well, not at all like
             | the promise. As always, there are no silver bullets and you
             | have to pick a stack that you can understand.
             | 
             | By the way, I made my own pitch for fully vanilla web
             | development here: https://plainvanillaweb.com/
        
               | merrywhether wrote:
               | IMO that blog series misses the point. Knowledgeable
               | motivated developers can make great experiences with any
               | technology, and conversely there are bad experiences
               | built with every technology. That series blames the
               | people involved for not being better, but that's just
               | blaming plane crashes on human error and calling it a
               | day.
               | 
               | - If the UK GSD is anything like USDS, using them for
               | comparison is like comparing a pro sports team to your
               | local high school's. They are an outlier specifically
               | created to be better than the average, so tautologically
               | their stuff will be better. Code For America is a
               | similarly odd comparison.
               | 
               | - The US has a massive gap in pay and prestige between
               | public and private sector developer jobs. It's not that
               | this means "worse" people work at public jobs, but in
               | general they start less experienced and can wind up in a
               | non-learning cycle as they don't get mentorship/guidance
               | from more expert folks, and if they do get good
               | independently they leave. It's really hard to convince
               | people to take a pay cut to work these jobs, and many of
               | the few willing to do so instead go to CFA, USDS, etc
               | because they want prestige and avoid all the other
               | inefficiencies in public jobs.
               | 
               | I could go on about the structural problems leading to
               | this, but suffice it to say that blaming React and other
               | JS frameworks is a miss. For some services it's lucky
               | they are online at all, and a slow web page is still
               | orders of magnitude faster than physical mail or god
               | forbid going to a physical office. The sites could
               | definitely be better but this is not fundamentally a
               | problem of technology choice.
        
             | no_wizard wrote:
             | You might find this project[0] interesting if you haven't
             | given it a look.
             | 
             | It was attempting to do something along the same lines as
             | you first suggest
             | 
             | [0]: https://github.com/jridgewell/jsx2
        
           | k__ wrote:
           | Wasn't the issue mostly solved with signals?
           | 
           | As far as I understand, signals make it much easier to keep
           | the DOM updates to a minimum.
        
             | resonious wrote:
             | It sounds to me like GP got told stuff exactly like this,
             | with the team eventually not actually doing the thing.
        
           | darepublic wrote:
           | More than once I got asked on interviews why react is faster
           | than vanilla JS and I had to tell them no, it isn't.
        
             | jameshart wrote:
             | The clue would be in the fact that react is _running in
             | vanilla JS_.
             | 
             | There is a persistent 'learned helplessness' tendency among
             | some developers to assume that the frameworks they are
             | using have access to magical mystical powers above and
             | beyond those that their own code can make use of.
             | 
             | Framework code might well be better optimized or more tuned
             | than the code you would write - but if you cared to employ
             | similar techniques you could achieve those same gains; on
             | the other hand, since by definition it's more flexible than
             | single-purpose code, it might not be optimal for your
             | usecase.
        
           | johnfn wrote:
           | The "performance angle" isn't really an angle. It gets
           | bandied around by junior devs new to React, but it's not the
           | primary selling point of React - in fact, it's not a selling
           | point at all. Don't believe me? Just go to http://react.dev
           | and look - no where on the site does it say that React is a
           | hyper-performant library. It's not! If you need blazing
           | performance, you're best off using something much more
           | minimal, or even vanilla JS.
           | 
           | When people say that React is fast, what they mean is that
           | React can dom-diff faster than a naive O(n) approach. It
           | means that updating a component with a thousand nested divs
           | won't crash out your browser, like it might if you were to
           | write the code by hand. It doesn't mean it's an objectively
           | high-performing framework.
           | 
           | What React _is_ good at is forcing you to write code in a
           | clear, comprehensible way. Having every engineer on your team
           | obey F(props) = state is a strict improvement over virtually
           | any other paradigm. (Yes, you can still make a tangle of
           | components if you try hard enough, but the complexity of the
           | tangle is capped significantly lower than the complexity of a
           | tangle of JS without any framework attached.)
        
         | dminik wrote:
         | This really just isn't true. If your state updates are at the
         | component subtree level (like react) a vdom is a good choice.
         | But, if you make your state changes more granular, you can get
         | away with skipping VDOM entirely and work with just* regular
         | dom nodes. Look at Solid or Svelte. No VDOM there, just pure
         | granular updates.
         | 
         | *List reconciliation still has to happen, but you don't need to
         | pull out an entire vdom. You just have to have some mapping
         | between list items and their resulting DOM nodes.
        
           | SkiFire13 wrote:
           | TBF while Solid and Svelte don't use a VDOM on which they
           | perform diffing, they still ultimately create a tree parallel
           | to the DOM which is used to track dependencies.
        
         | AltruisticGapHN wrote:
         | I'm having fun using lit-html with vanillajs, after I saw a
         | tweet from Marc Grabanski suggesting he didn't use the full Lit
         | library. Admittedly I am then not taking advantage of all the
         | reactivity goodness, but I also really dislike the decorators
         | syntax and 95% of the time I just don't need the reactivity
         | after the first render.
         | 
         | It works great! I was amazed at how you can do so much in
         | templates, it's pretty much everything I could do in Vue
         | templates, though a little more verbose.
         | 
         | I built my own `VanillaComponent` class, which has a mount()
         | method which calls the render() function which I define on the
         | child class.
         | 
         | My VanillaComponent class looks like this:
         | import { html, render } from "lit-html";
         | abstract class VanillaComponent {           abstract render():
         | ReturnType<typeof html>;                    private
         | _mountPoint?: HTMLElement;                    mount(this:
         | VanillaComponent, target: HTMLElement) {
         | target.textContent = '';             this._mountPoint = target;
         | this._update();           }                    _update() {
         | let templateResult = this.render();             let rootPart =
         | render(templateResult, this._mountPoint!);           }
         | }
         | 
         | So I can write something like                   class
         | MyComponent extends VanillaComponent {
         | constructor(props: { label: string }) {             this._props
         | = props;           }                      render() {
         | return html`<button>${this._props.foo}</button>`;           }
         | }
         | 
         | Then I can instance like so:                   let myComponent
         | = new MyComponent({ label: "I am a button" });         let
         | target = document.querySelector("#demo");
         | myComponent.mount(target);
         | 
         | The base class stores the root node (target), so later I can do
         | myComponent.update()
         | 
         | to re-render, taking advantage of lit-html's "diffing" logic.
         | 
         | However something I have not been able to solve with lit-html
         | only, is when I compose parent and child components I have to
         | do something like :                   class MyDialog extends
         | VanillaComponent {           render() {             let
         | childComponent ...  // another VanillaComponent previously
         | instanced             return html`               <div>
         | ${childComponent.render()}               </div>
         | 
         | So the child component I need to explicitly call render() to
         | get the TemplateResult for the parent template.
         | 
         | But this means I can not do `childComponent.update()` because I
         | don't know the root element of child component, since I did not
         | mount it explicitly myself.
         | 
         | I mean technically because of the lit-html optimizations, I can
         | do `.update()` on myDialog (the parent component) after any
         | child component's props changes, and it will only re-render
         | what is necessary... but let's say my child component has like
         | 1000 cards... it seems very wasteful and it would be ideal if I
         | could re-render only the child.
         | 
         | I wonder if there is a trick to get around that with just lit-
         | html?
        
           | mst wrote:
           | It's always worth checking the lit built in directives list
           | for the one you've still missed (or at least it is for me ;).
           | 
           | I think in this case the ref() directive - i.e.
           | https://lit.dev/docs/templates/directives/#ref - may be what
           | you want. If it isn't exactly, reading how it's implemented
           | would be my first step towards building something similar
           | that is.
        
         | croes wrote:
         | Svelte and SolidJs work pretty well without VDOM
        
         | kolme wrote:
         | Nice, I love lit-html(1)!
         | 
         | I wanted to add my two pennies to the discussion. You are of
         | correct that with that approach you lose the declarativeness
         | but sometimes you don't need that, if the thing is mostly
         | static.
         | 
         | I went this road many years ago for a project. The nice thing
         | of this approach is getting rid of all the ugly DOM API but
         | enjoying it's performance over innerHTML.
         | 
         | (1) I absolutely love lit-html but don't like the rest of the
         | lit components framework. Luckily you can use it independently!
        
         | skrebbel wrote:
         | JSX in SolidJS directly returns DOM elements much like in the
         | top part of this post, yet it does not have these
         | disadvantages. It's true that strictly put it's not immediate
         | mode like React and Lit are, but the framework is designed such
         | that there's few practical downsides to that.
        
         | PKop wrote:
         | UI is not a pure function of state[0], "UI state" is relatively
         | stable and does not have to be recreated constantly when data
         | input changes.
         | 
         | [0] https://blog.metaobject.com/2018/12/uis-are-not-pure-
         | functio...
         | 
         | >you want to be able to reevaluate your templates repeatedly
         | with new state
         | 
         | No you don't. It is inefficient and increases complexity. You
         | then have to extract and keep track of state yourself where the
         | platform/UI components could have done much of this themselves.
         | Calling the same method over and over again is wasteful.
         | So we don't do that.              First, we did not start with
         | the obviously incorrect premise that the UI is a simple "pure"
         | function of the model. Except for games, UIs are actually very
         | stable, more stable than the model. You have chrome, viewers,
         | tools etc. What is a (somewhat) pure mapping from the model is
         | the data that is displayed in the UI, but not the entire UI.
         | So if we don't make the incorrect assumption that UIs are
         | unstable (pure functions of model), then we don't have to
         | expend additional and fragile effort to re-create that
         | necessary stability.
        
         | lucideer wrote:
         | If the above is what you need there's not strong reasons not to
         | use React or similar. But for most things that will lead to an
         | interest in "Vanilla JSX" this line of thinking is premature
         | optimization - the advantages of vdom are extant but enormously
         | overstated. JSX has many other advantages.
         | 
         | It's also not even an either-or. I've worked on a codebase that
         | did both: React was loaded for some views & others were served
         | with a lightweight JSX renderer.
        
       | recursive wrote:
       | I also made a UI library based on the idea of jsx template
       | expressions that produce real DOM nodes. It also binds model
       | objects to attributes, eliminating some of the imperative event
       | handler boiler-plate. I think it's a great idea, but of course I
       | would.
       | 
       | https://github.com/tomtheisen/mutraction
       | 
       | It lets you do stuff like this.                   const model =
       | track({ clicks: 0});         const app = (             <button
       | onclick={() => ++model.clicks }>                 { model.clicks }
       | clicks             </button>         );
       | document.body.append(app);
        
       | cyanydeez wrote:
       | I just don't understand how people can configure their brains to
       | parse html inside JavaScript
        
         | zazaulola wrote:
         | You're not alone. Someone suggested that the W3C should convene
         | a Community Group to discuss JSX, but the grown guys involved
         | in writing standards immediately scrapped the idea.
        
         | 1attice wrote:
         | There's a trick to it. Kind of like one of those 'magic eye'
         | stereograms that were popular in the nineties. You sort of
         | unfocus and boom, there it is.
         | 
         | It also reminds me of that Douglas Adams line about flying:
         | it's the trick of falling and completely missing the ground, so
         | in order to do it, you can't think about it too hard.
        
         | xigoi wrote:
         | If there can be JS inside HTML, why not HTML inside JS?
        
       | flowerlad wrote:
       | This is very similar to Vanilla TSX:
       | https://github.com/wisercoder/uibuilder
       | 
       | Here's an app written using Vanilla TSX:
       | https://github.com/wisercoder/eureka/tree/master/webapp/Clie...
        
       | andrewstuart wrote:
       | Just out of interest I wanted to see something a little bit
       | similar in Web Components:                   <html lang="en">
       | <body>           <h1>Web Components Examples</h1>
       | <h2>Counter Component</h2>           <counter-
       | component></counter-component>           <h2>Clickable Button
       | Component</h2>           <clickable-button></clickable-button>
       | <h2>Toggler Component</h2>           <toggler-
       | component></toggler-component>           <script>
       | class CounterComponent extends HTMLElement {
       | constructor() {                 super();
       | this.count = 0;                 this.button =
       | document.createElement('button');
       | this.button.textContent = this.count;
       | this.button.addEventListener('click', () => {
       | this.count++;                   this.button.textContent =
       | this.count;                 });
       | this.attachShadow({ mode: 'open' }).appendChild(this.button);
       | }             }                      class ClickableButton
       | extends HTMLElement {               constructor() {
       | super();                 this.clicked = false;
       | this.button = document.createElement('button');
       | this.button.textContent = "Click me!";
       | this.button.addEventListener('click', () => {
       | this.clicked = !this.clicked;
       | this.button.textContent = this.clicked ? "Clicked!" : "Click
       | me!";                 });                 this.attachShadow({
       | mode: 'open' }).appendChild(this.button);               }
       | }                      class TogglerComponent extends HTMLElement
       | {               constructor() {                 super();
       | this.on = false;                 this.button =
       | document.createElement('button');
       | this.button.textContent = "OFF";
       | this.button.addEventListener('click', () => {
       | this.on = !this.on;                   this.button.textContent =
       | this.on ? "ON" : "OFF";                 });
       | this.attachShadow({ mode: 'open' }).appendChild(this.button);
       | }             }             customElements.define('counter-
       | component', CounterComponent);
       | customElements.define('clickable-button', ClickableButton);
       | customElements.define('toggler-component', TogglerComponent);
       | </script>         </body>         </html>
        
       | slmjkdbtl wrote:
       | I never understand the appeal of JSX over something like
       | h("div", {}, [         h("p", {}, "this is easy"),
       | ...list.map((l) => h("li", {}, l),       ])
       | 
       | With this you automatically get loops, variable interpolation etc
       | without having to invent a compiler and new syntax. Can someone
       | help me understand?
        
         | fredmerc wrote:
         | Keep going down that logical rabbit hole. You end up with
         | Common Lisp!
        
         | erikpukinskis wrote:
         | You might be confusing JSX for something else. In JSX you also
         | don't need new syntax for loops. JSX Is JavaScript, as people
         | like to say.
         | 
         | But to your point, JSX doesn't really do much. Your h function
         | is basically what React.creatElement does. Google "React
         | without JSX" and you'll see how it looks.
         | 
         | JSX is just syntactic sugar over React.creatElement. And that
         | is what makes it so nice... there _are_ no special constructs
         | for loops, or variables, or components. They are actual
         | JavaScript loops, JavaScript variables, and JavaScript
         | function.
         | 
         | It makes JSX easier to reason about than most templating
         | languages.
        
         | sim0n wrote:
         | I would assume that lot of people just find the JSX equivalent
         | a lot more readable and familiar (a matter of opinion, of
         | course.)                 <div>         <p>this is easy</p>
         | {list.map((l) => <li>{l}</li>)}       </div>
         | 
         | > you automatically get loops, variable interpolation etc
         | without having to invent a compiler and new syntax
         | 
         | To be fair to JSX, you use regular loops, interpolation, etc
         | without any different syntax (`{}` accepts a vanilla JS
         | expression), you just obviously need the compiler step to de-
         | sugar the element tags to `createElement` calls.
        
           | slmjkdbtl wrote:
           | Yeah the syntax is almost identical to vanilla js, but
           | requiring a compiler is quite cumbersome compared to the
           | advantage it provides imo.
        
             | presentation wrote:
             | That said if anything pretty much all of the new school
             | frameworks and many of the tools in their ecosystems are
             | already dependent on compilers for optimization anyway,
             | react itself is introducing a compiler in the latest
             | versions.
             | 
             | Anyway I prefer the html looking syntax if anything because
             | it looks like the output on the page. That's dependent on a
             | project coding style that doesn't unnecessarily wrap things
             | in components, which for my company's product I've set as a
             | standard.
        
             | littlestymaar wrote:
             | Requiring a compiler also allows to catch mistakes at
             | compile type, which is much more efficient in terms of
             | development.
        
         | plonq wrote:
         | I've wondered the same thing. I think one benefit is that it
         | looks like HTML, which means it looks similar to what you see
         | in the browser's DevTools, which makes it easier to compare and
         | debug.
        
           | usrusr wrote:
           | It also makes it easier to see what it's _not_ : at a glance,
           | the "p" could really be anything until you scan the context.
           | The <p> isn't a string (that on further examination turns out
           | to get used for marking up a paragraph), it _is_ a paragraph
           | demarkation (in vdom, but still).
        
         | whichdan wrote:
         | Elm works a lot like this and it's quite nice.
        
         | dimal wrote:
         | Here's my perspective. I never understand how some people could
         | look at the code you pasted and think that's just as good. But
         | different people's brains process information differently. Your
         | example has a lot of punctuation that's very difficult for me
         | to parse quickly. I don't see the DOM structure that's being
         | created unless I manually pick the syntax apart in my mind, but
         | understanding the DOM structure at a glance is far more
         | important to me than whether I need a compiler. For the record,
         | I'm neurodivergent. I hope that helps.
        
           | slmjkdbtl wrote:
           | Yes I can understand it helps if it looks like DOM on first
           | sight, I'm thinking more about the functional aspect where it
           | can achieve the same thing without requiring a compiler and a
           | new syntax (altho you can argue it's not new syntax just js +
           | html)
        
             | dimal wrote:
             | It doesn't achieve the same thing, though. Functionally,
             | for the computer, it's the same. But code has two
             | audiences: the computer and the coder who has to read and
             | write it. And from my perspective, the human is more
             | important than the computer. And JSX is more than a
             | convenience at first glance. You read a lot more code than
             | you write. If all of my code was written like this, it
             | would add significant cognitive load, make the code more
             | difficult to reason about and slow me down.
        
         | 65 wrote:
         | Because that code is very hard to read, especially with a
         | complex HTML structure.
        
         | codingdave wrote:
         | For a single file or simple app, sure, your style works fine.
         | But when you get a few hundred components in a complex app,
         | importing them into each other and writing them as JSX tags
         | feels like a simple, easy to understand syntax, as least to me.
         | 
         | And that is what a lot of the pushback against React seems to
         | come down to as well -- it is overkill for simple things. And
         | it is. But different people doing different apps with different
         | levels of complexity... all have different needs.
         | 
         | So it is not as simple as one having appeal over the other.
         | They are different tools for different problems.
        
       | girvo wrote:
       | Does the final example not work in Firefox for anyone else? It
       | worked in Edge, but not Firefox for me                   Uncaught
       | (in promise) TypeError: Map.groupBy(...).entries().map is not a
       | function
        
         | iammrpayments wrote:
         | Object.groupBy doesn't seem to be available to all browsers
         | before march 2024: https://developer.mozilla.org/en-
         | US/docs/Web/JavaScript/Refe...
        
       | ilrwbwrkhv wrote:
       | Imba is what anyone interested in this sort of thing should look
       | at. I have no idea why it is not more popular. Maybe because JS
       | devs falls for Faang marketing easily.
       | 
       | https://imba.io/
        
         | xigoi wrote:
         | Many programmers seem to be scared of anything that doesn't
         | have semicolons and braces.
        
       | EugeneOZ wrote:
       | As often happens with minimalistic approaches, it only looks
       | interesting on very small and very simple examples.
       | 
       | After "How would they handle large data?" it turns into an
       | unreadable mess.
       | 
       | Communication between elements is not covered, global deps, DOM
       | updates scheduling, content projection, and so on - you "just
       | don't need it" in small demo examples, but you do need it in the
       | real apps.
        
       | frabjoused wrote:
       | It's already solved. It works well. Just walk away.
        
       | hizanberg wrote:
       | Anyone else used Hono with SSR JSX? [1]
       | 
       | Was super productive and easy to create a Cloudflare Worker Web
       | App that's free to host thanks to Cloudflare's generous 100k
       | daily worker request limit.
       | 
       | Generally don't believe in serverless for larger Apps, but for
       | small websites that you just want to create, deploy and ignore -
       | it's great!
       | 
       | https://hono.dev/docs/guides/jsx
        
       | drikerf wrote:
       | Nice project! I do wonder though if jsx is the best way to
       | represent elements in code?
       | 
       | Clojure datastructures makes this so much more enjoyable.
       | Everything is just basic lists and maps which makes it very
       | flexible and powerful.
       | 
       | [:ul [:li "task 1"] [:li "task 2"]]
       | 
       | It's weird that it's not more common for making web apps.
        
         | globular-toast wrote:
         | There is a library for Python called htpy that does this.
         | 
         | Trouble is if you're used to HTML it can take a while to get
         | used to it. It's like a learned helplessness or something.
        
         | edflsafoiewq wrote:
         | There are a lot of DOM util libraries that look like
         | h("ul", h("li", "task 1"), h("li", "task 2"))
         | 
         | This is called "hyperscript-style" after an early library that
         | used it. This is basically what JSX compiles to too. There used
         | to be a lot of JSX vs hyperscript debates.
         | 
         | There's also variants like h.ul(h.li("task 1"), h.li("task 2"))
         | using Proxies now too.
        
       | mg wrote:
       | What is the benefit of mixing js and html?                   el =
       | <button>Click me</button> as HTMLButtonElement;
       | 
       | What would be the downside of                   el =
       | html.button('<button>Click me</button>');
       | 
       | ?
       | 
       | That way no compilation step would be needed and debugging would
       | be easier as the code executed in the browser is the same code
       | the developer writes.
        
         | littlestymaar wrote:
         | With the first example you have syntax highlighting and
         | compile-time check.
         | 
         | With the second of you have stringa.
        
           | mg wrote:
           | Why wouldn't one be able to tell syntax highlighters and code
           | checkers that the string that goes into the html.something()
           | functions is html?
        
           | Joeri wrote:
           | If you use a html`` tagged template literal combined with the
           | html-in-template-string vs code extension you get syntax
           | highlighting. A simple html identity literal function is a
           | one-liner: https://developer.mozilla.org/en-
           | US/docs/Web/JavaScript/Refe...
        
         | moffkalast wrote:
         | The benefit is that it makes people puke from looking at it so
         | you have more job security I guess. Putting xml onto the same
         | line with a scripting language is like mixing toothpaste and
         | orange juice.
         | 
         | I don't understand why people take such offense to calling
         | document.createElement() or document.getElementById() or kind
         | of document. or window. function. It's consistent and native.
        
       | whazor wrote:
       | I don't see why the type casting (as HTMLButtonElement) is
       | needed. Because document.createElement("button") returns
       | HTMLButtonElement in TypeScript.
        
       | miika wrote:
       | I used to explore similar stuff and prototyped something I call
       | "Vanilla Components" but then in the end I fell in love with Web
       | Components and quit React (and all other frameworks).
        
       | merlindru wrote:
       | VanJS deserves a mention here! https://vanjs.org/
       | 
       | Another interesting thing is that other JSX libraries like
       | Solid.JS also return DOM nodes, and I love that this idea is
       | gaining traction
       | 
       | The closer we get to the platform we're using, the better. Being
       | removed by layers of abstractions CAN be useful, but in practice,
       | I haven't found a use for abstracting away the platform. (yet.)
       | 
       | Maybe huge projects like Facebook benefit from this tho (which I
       | haven't worked on)
        
         | croes wrote:
         | Isn't SolidJS useless in the bundle size comparison?
        
           | novocantico wrote:
           | That may be a point in favor of imlib.
           | 
           | Technically this is the only code bundled with vanilla jsx:
           | 
           | https://vanillajsx.com/@imlib/jsx-browser.js
        
       | dqh wrote:
       | Those interested in this space may find my fairly unknown project
       | interesting: https://nakedjsx.org/
       | 
       | It started as a static site generator but added a bunch of
       | support for client JavaScript too.
        
       | n3storm wrote:
       | For me is like old PHP where HTML and controlling and data access
       | was all around. We use to call it spaghetti code.
        
       | NaN1352 wrote:
       | How does this stack up aginst using lit-html?
        
       | NaN1352 wrote:
       | I'm having fun using vanilla js with lit-html. Using string
       | templates instead of jsx. VSCode extensions for lit make it
       | almost identical to editing vue templates with type checking etc
        
       | cies wrote:
       | I frown at JSX. Just a layer of abstraction that is so "leaky"
       | that you have to know what actually goes on in the layers below
       | or you are fucked.
       | 
       | It looks simpler at first glance/ to a untrained eye; but it's
       | just adding complexity without really solving any problems.
       | 
       | I like approaches like Kotlinx.html, scalatags, Elm's HTML
       | package or HtmlFlow. They are also abstractions, but they add
       | typesafety that html-as-a-string does not offer. On top of that
       | you get breakpoints, code completion, and you can keep working in
       | one language.
        
       | talkingtab wrote:
       | A side question. The advantage of JSX I see is the ability to
       | connect, declaratively, components. I find this very helpful in
       | terms of understanding programs I write. I wonder if I use React
       | not because of the virtual dom, but simply because of JSX.
       | 
       | So I would like to explore the ability to use JSX in non-DOM
       | environments. react-three-fiber does this with Threejs, but then
       | it is still React oriented. I found this article about parsing
       | JSX https://blog.bitsrc.io/demystifying-jsx-building-your-own-
       | js.... And I know babel has something that parses JSX.
       | 
       | Does anyone have recommendations for doing this. Threejs to me a
       | good candidate - a non React version, since it is a hierarchical
       | system (scene, meshes, materials etc), but I suspect there are
       | other applications.
       | 
       | I made an attempt to implement a Javascript version of Hickey's
       | transducers - a sort of conveyor belt of functions and that is
       | another instance of a series of processing steps that might be
       | best represented in JSX
        
         | erikpukinskis wrote:
         | I see what you're getting at, but technically the virtual DOM
         | is what makes JSX declarative.
         | 
         | JSX doesn't actually write anything, it's just a templating
         | language over React.createElement.
         | 
         | It's the virtual DOM that actually syncs those structures
         | created by createElement to the real DOM. So it's the virtual
         | DOM that allows you to write your code declaratively.
         | 
         | That's evidenced by OP's project, which is JSX without the
         | declarative piece. You just get an Element and then you have to
         | update it imperatively if you want to change anything.
        
       | andruc wrote:
       | It's very strange that when I land on the page for the very first
       | time, I land halfway down the page and I'm staring at a block of
       | random code.
       | 
       | Not what you'd expect to see.
        
         | andruc wrote:
         | #real-todolist has an autofocus element and I'm using Firefox
        
           | novocantico wrote:
           | Oops. Fixing now.
        
             | andruc wrote:
             | \o/
        
       | andruc wrote:
       | Any comparisons on performance?
        
       | emadda wrote:
       | One of the reasons for JSX originally was to reduce usage of the
       | DOM APIs, as they are slower than direct JS object manipulation.
       | The JSX diff of prev/next allows you to minimize DOM API calls.
       | 
       | I would guess there is more overhead in creating a dom element
       | than a JS object (which JSX elements compile to).
        
         | austin-cheney wrote:
         | React came out in 2013. At that time object manipulation would
         | likely have been, at best, only marginally faster than writing
         | to the DOM.
         | 
         | First, you have to understand that at that time Firefox was
         | about 500x faster at accessing the DOM than Chrome and about
         | 250,000x faster accessing the DOM via the API methods than via
         | querySelectors. Firefox and Chrome performed about equally in
         | use of querySelectors with Chrome being a tiny bit faster. So,
         | the DOM was already fast, but occupied a different memory space
         | than JS.
         | 
         | At any rate the original motivation had nothing to do with
         | performance. The goal was to introduce a template system that
         | fit with React's state/component system. JS modules weren't a
         | thing yet, so code organization was very different at that time
         | and centered around concepts like AMD and Common.js, though it
         | was mostly some form of AMD typically require.js.
         | 
         | The design of the template system in Vue was created to solve
         | for the exact same conditions according to the internal
         | organization of Vue.
        
           | emadda wrote:
           | Respectfully, my experience says otherwise:
           | 
           | https://jsben.ch/cSWJa
           | 
           | - JS object appears to be at least 2x faster than
           | document.createElement() (Chrome)
           | 
           | - Note: JS object only loosely represents JSX element so it
           | is a bit unfair. But with actual JSX objects I would assume
           | it is still somewhat faster than the DOM API.
           | 
           | https://youtu.be/DgVS-zXgMTk&t=1532
           | 
           | - Pete Hunt, one of the React devs, says "JSX is faster than
           | the DOM because it is JS memory."
        
       | NohatCoder wrote:
       | For anyone who can live without <> syntax I made DOM Maker, no
       | compilation step, no injection vulnerability footguns, just make
       | a bunch of function calls in a tree structure, and you get DOM
       | with the same tree structure, complete with non-string event
       | handlers.
       | 
       | Mostly I just do Vanilla.js, but the vanilla DOM creation
       | functions turn really verbose, I got tired of that and created
       | this to cut back on code size and increase readability.
       | 
       | There are other libraries that do something similar, but in my
       | own very biased opinion this is one of the better.
       | 
       | https://github.com/NoHatCoder/DOM_Maker
        
       | jwtorres wrote:
       | I genuinely don't understand why anyone would be interested in
       | using frameworks on top of JS. None of them can do anything that
       | pure JS can't do (+libraries), they just make it less readable
       | and less intuitive compared to the original C-like syntax of JS.
       | JS libraries make sense, of course, but why keep messing with the
       | syntax?
        
       | nf17 wrote:
       | Great job, is there something similar but for SwiftUI?
        
       | xwall wrote:
       | No matter how complex your app is but still React will not break,
       | performance on web is not a big issue as benchmarks say, even a
       | junior developer can achieve 90%+ lighthouse score, but any
       | senior developer may fail to ship it successfully.
       | 
       | ultimately go to react.dev because: "Maturing is realizing React
       | is best"
        
       ___________________________________________________________________
       (page generated 2024-08-17 23:01 UTC)