3 ms·
> The direct semantics of JSX are "transform this syntax into this nested sequence of function calls and this layout of arguments". Not exclusively. SolidJS, f
by MrJohz 1y ago
> The direct semantics of JSX are "transform this syntax into this nested sequence of function calls and this layout of arguments".
Not exclusively. SolidJS, for example, transforms the syntax into string templates with holes in them. The "each element is a function call" approach works really well if those calls are cheap (i.e. with a VDOM), but if you're generating DOM nodes, you typically want to group all your calls together and pass the result to the browser as a string and let it figure out how to parse it.
For example, if you've got some JSX like:
<div>
<div>
<span>{text}</span>
<div>
<div>
You don't want that to become nested calls to some wrapper around 'document.createElement`, because that's slow. What you want is to instead do something like
const template = parseHtml(`
<div>
<div>
<span></span>
<div>
<div>
`);
template.children[0].children[0].innerText = text
This lets the browser do more of the hard parsing and DOM-construction work in native code, and makes everything a lot more efficient. And it isn't possible if JSX is defined to only have the semantics that it has in React.
- recursive 1y ago> You don't want that to become nested calls to some wrapper around 'document.createElement`, because that's slow. It's really not slow. It might seems slow if you're using react behavior which re-invokes the "render function" any time anything changes. But eventually they get reconciled into the DOM which creates the elements anyway. And most other code bases are not based on this reconciliation concept. So I don't think that's a given.
- MrJohz 1y agoIt's significantly slower than letting the browser do the work for you. Obviously performance isn't the only concern, but (a) as a user, I don't want people wasting my CPU cycles unnecessarily, and (b) I've worked on applications where ever single millisecond counted, and the createElement approach would have made a material difference to the performance of the application overall. Also, there's no reconciliation happening here. In SolidJS, as well as in Vue in the new Vapor mode, and Svelte, the element that is returned from a block of JSX (or a template in Svelte) is the DOM element that you work with. That's why you don't need to keep rerendering these components - there's no diffing or reconciliation happening, instead changes to data are directly translated into updates to a given DOM node. But even if you don't need to worry about subsequent re-renders like with VDOM-based frameworks, you still need to worry about that initial render. And that goes a lot quicker if you can treat a JSX block as a holistic unit rather than as individual function calls.
- WorldMaker 1y ago`document.createElement` performance has come a long way in the last few years. The HTML "string" parser is incredibly well optimized in every browser, but the performance difference between smash a string into `innerHtml` and `document.createElement` approaches has shrunk a lot, especially in the time since React started doing so much VDOM work to avoid both tools as much as possible. The difference shrinks even further with `<template>`/HtmlTemplateElement, its secondary/content `document`s for `document.createElement` and `document.importNode` being faster for cloning+adoption of a `template.contents` into the main document than string parsing. I've got work-in-progress branch in a library of mine using JSX to build HtmlTemplateElements directly with `document.createElement` and right now `document.createElement` is the least of my performance concerns and there is no reason to build strings instead of elements. (ETA: There are of course reasons to serialize elements to strings for SSR, but that's handy enough to do with a DOM emulator like JSDOM rather than need both an elements path and a string path.)
- recursive 1y agoWe're talking about the behavior of standardized JSX. Different frameworks have different approaches. This supports the only point I'm trying to make here. Which is that there's no expected standard behavior of JSX on which tostandardize.