This all feels rather half-baked. Why can't the parser/prprocessor distinguish between that "class" and "class" in JS source code? We can have reusable HTML snippets (some may call components) with normal templating engines easily. Look at something like Jinja2 and how to reuse blocks and macros. Yes, some React component can encapsulate its own interactive behavior. That is only because we are already writing JS though, so we can already write frontend logic. But do we actually want that? Coupling state and behavior? I think we might not. Writing a script that gets served only on those rendered templates, where it is needed is not so hard either, when using a normal templating engine.
React is simple. Here is your data, and here is a function that transforms that data into a view.
Templates are terrible, and that is a hill I am willing to die on.
Is that aspect so much different from templating engines? In templating engines the rendering step is simply abstracted one step further: You get a generalized render function, that you pass data to and a template to render with that data. That is also a function to turn your data into a view. I don't see how React is better in that aspect.
> This all feels rather half-baked. Why can't the parser/prprocessor distinguish between that "class" and "class" in JS source code?
Remember that React is "just JavaScript", JSX is a syntax transformation of JavaScript. When you use `className` in your JSX, you're using the standard DOM Attribute [1]. You wouldn't use `class` either in vanilla JS to set the CSS class, you'd use `className`.
https://developer.mozilla.org/en-US/docs/Web/API/Element/cla...
In a usual templating engine valid HTML is also valid template. One does not have to use templating engine specific things. A HTML snippet can simply be HTML. No harm done. But in JSX one cannot use normal HTML, as shown by the `class` case.
> However, that means, that now one has something, that is neither looking like HTML, nor is it looking like JS, even if it may be JS through some pre-processing (but then actually it is not really JS?).
Yes, it's not HTML or JS, it is JSX. It's an XML-based syntax to declaratively write JavaScript. It's optional too - one can write the function calls directly in JS, and indeed that's what people did before JSX existed. `React.createElement("div", React.creatElement("span"),...)`. It could be worth using a REPL [1] to gain an intuition of the JavaScript that is produced from transforming different JSX examples.
> The result is, that one has to learn some different syntax that is specific to React.
JSX was originally created for React, but now is not specific to React, other libraries and frameworks use it as well. It's a general purpose XML-based syntax for writing JavaScript declaratively.
And yeah, if you want to use JSX you have to learn it. It's easy to learn if you know JavaScript and XML and shouldn't take very long. It's XML and then anything inside curly braces is a JavaScript expression.
If you're using TypeScript replace everything "JS" I'm saying with "TS", it's the same result. And obviously type checking works without issue because it's a syntactic transformation to TS, not a semantic transformation.
> In a usual templating engine valid HTML is also valid template. One does not have to use templating engine specific things.
JSX is not an HTML templating engine [2]. JSX is a way to write JavaScript declaratively using an XML-based syntax.
> But in JSX one cannot use normal HTML, as shown by the `class` case.
Yes, as expected. JSX is not an HTML templating engine, it's a way to write JavaScript declaratively using an XML-based syntax. In JavaScript, you use the DOM APIs [3], not HTML attributes [4].
[2]: https://legacy.reactjs.org/docs/introducing-jsx.html
[3]: https://developer.mozilla.org/en-US/docs/Web/API/Document_Ob...
[4]: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes
But you know, if you are trying to put HTML templates in separate files, you have to now send extra HTTP requests. That's an even bigger no no.
In other languages, you can just put your template in a separate file and load it from your package/.jar/assembly. Super easy and most importantly, 100% standard and provided by the environment.
So people just settled with React because it worked and no successfully invented a standard bundle format for the web.
F' it we said.
It's not actually, with HTTP/2. The separate requests are all multiplexed over the same connection, often with prefetching, and compressed together so that there's little to no overhead vs. putting them in the same file.
This illustrates a common failure point for web frameworks though. They encode a lot of folk knowledge about how the web works, but that folk knowledge becomes obsolete as browsers change.
Another prominent React example fits into this category: the virtual DOM. React assumed that DOM manipulations were slow and Javascript manipulations were fast, and so they built up an internal representation of the DOM in Javascript so they could manipulate that one and diff the change to apply it to the real DOM. This was true from approximately 2008 (when V8 introduced JS JITting) to 2013 (when Blink/Webkit/Firefox all moved to a dirty-bit system for DOM manipulations), which not coincidentally is when React was designed. But since then, DOM manipulation has been just pointer swaps and a dirty bit flip, and if you're careful not to invoke any operation that triggers a reflow and repaint you can make your modifications directly in the DOM for roughly the same cost as making them in JS. Since React is declarative it could easily have enforced the no-reflow rules without the virtual DOM, but because DOM manipulations were expensive when its designers learned web programming, it introduces an unnecessary concept.
But HTTP/2 is not the right example. You're missing some things on the web timeline.
Long before HTTP/2 (time in web terms), and after React (and Angular, etc.) came about, people created actually-popular bundler toolchains that can bundle arbitrary files together and then incrementally load them as needed. This effectively fixed the multiple HTTP request problem long before HTTP/2 existed. Efficient template files have been possible for years. (Granted, not anything standard though.)
The issue right now is that someone has to make a full toolchain with strong developer support to make this a de-facto and popular way to distribute apps. Just because you have a bundler or HTTP/2 doesn't mean you have a nice way to make use of it. You need a nice library. Your usage examples need to look pretty. It needs to work with other toolchains. It needs to look like your library will be supported for a long time, just like how React was supported by Facebook.
You can't just write a blog post about how it's possible because you're basically asking your readers to invent and maintain a library or worse, roll their own internal library that will confound people at their company.
> What forces layout/reflow. The comprehensive list.
> All of the below properties or methods, when requested/called in JavaScript, will trigger the browser to synchronously calculate the style and layout*. This is also called reflow or layout thrashing, and is common performance bottleneck.
Slightly longer answers:
[modifies] https://developers.google.com/speed/docs/insights/browser-re...
[measures] https://gist.github.com/paulirish/5d52fb081b3570c81e3a
Also there's a bunch of exceptions where you can modify things without triggering a full reflow. Anything that takes elements out of normal flow (position: fixed, position: absolute, float:, overflow: hidden) creates a layout boundary where changes inside only reflow the containing element. Any element with a transform: or opacity: property gets rendered as a 2D texture on the GPU, and then you can do subsequent transform/opacity animations purely on the GPU without touching the CPU. Used to do this to make performant animations on mobile devices.
Most projects that I have been involved with have some kind of build system that does all sort of magic. It should be possible to include the template in the JS file during the build process
Here's an example of using a web component in a JSX template (look for zx-listeditor): https://github.com/wisercoder/uibuilder/blob/master/WebCompo...
Here's how the web component is implemented, also using JSX: https://github.com/wisercoder/uibuilder/blob/master/WebCompo...
{ tag: 'div', padding: '2px', position: 'absolute', content: [myText] }
than <div style="padding: 2px; position: 'absolute'">${myText}</div>
The main reason I ended up settling for JSX was just convention: I don't want to be the one with my own unique format for UI trees unless I can convince everybody else to use my format.Note that Jetpack Compose has a very similar declarative reactive paradigm as React, but represents components with Kotlin language mechanisms. IMHO I like it much better, because it's much more composeable.
It's new and has no significance for the history. But I think it's relevant to point out that <template id="myhtml"><div></div></template> isn't horrible.
And that those articles about web components are doing a really bad job of using constant strings instead of this.shaddow.innerHTML = getElementById("myhtml").innerHTML.
It's bad because it's inline and your templates have no obvious place to go. You also can't import them on the fly (or rather, it's as idiomatic to import as any HTML). And obviously, because they have no effect on HTML and can only be used in javascript
Yeah it’s another framework with its own quirks but it lets me think about the UI in the same way I’ve thought about it for 25 years. For someone like me that’s a godsend.
[0]: https://lit.dev/
> This is what JSX compiles to behind the scenes.
Oh, it is much worse than that. By classic default it is:
React.createElement('div', { /* props and attributes ... */ },
React.createElement('strong', { /* ... */ }, text))
Recent updates and other JSX frameworks simplified the name of `React.createElement` to just `jsx` or `h`. I've seen projects that manually write `h` calls like that everywhere, and it is indeed terrible.(Source: I've just completed a bunch of crazy TSX work and got pretty familiar with the compiled forms.)
Doing something like this.shadow.innerHTML = `your HTML` with web components is terrible. document.createElement() is terrible. $('div').appendChild() is terrible. <script language="html" name="my-template"><!-- --></script> is terrible. HTML(Div(Strong(text))) is terrible*. Storing templates as JSON and writing a one-off loader is terrible. <div style="display:none">template</div> is terrible. I've done it every possible way and they are all terrible.
JSX fixed all that.
The biggest previous attempt at something like JSX was E4X where you could embed XML straight into JS, which was kinda nice except it added the entirety of XML and its complexity. I creamed when it came out but then I tried it and it was not it. (E4X ended up surviving a little longer in Adobe Flash though.)
E4X: https://en.wikipedia.org/wiki/ECMAScript_for_XML
*This is what JSX compiles to behind the scenes.