DEV Community

Cover image for A Look at Compilation in JavaScript Frameworks

A Look at Compilation in JavaScript Frameworks

Ryan Carniato on June 01, 2021

In 2017 Tom Dale, wrote Compilers are the New Frameworks. And he was right. In 2017 things were already heading that way and have only continued on...
Collapse
 
hoichi profile image
Sergey Samokhov

One thing that worries me about this development is that compiled frameworks seem to phase more or less general-purpose compiled languages like ReScript or PureScript or ClojureScript. Sure, both Svelte and SolidJS support TypeScript, but that requires effort on the framework maintanters' part, so how likely is it that, say, Solid will ever support ReScript? Sure, you can somehow marry the compiled framework and an AltJs language (I think in ReScript's case you could even add genType to generate TS, but it's still not a perfect setup: Svelte components just consume ReScript functions, so there's no ReScript features in UI: no concise sum types with exhaustive pattern matching, no runtime currying or pipes.

So the whole situation only reinforces the TS monopoly. And it's not that TS is an awful language, but any monopoly leads to stagnation. And also I think there are still better languages than TypeScript, so the whole situation leaves you with the choice between a modern compiled framework with TypeScript and a nice business-logic friendly compiled language that wraps good old React (ReScript, PureScirpt, ClosureScript), or Preact (Mint), or its own VDom-based implementation (Elm). Or, if you're desperate enough, you could try to convince the language maintainers to alter their JSX compilation to support Solid 🤔

Collapse
 
ryansolid profile image
Ryan Carniato

The latter is what we've been looking at with Solid. They support React. Honestly if we could just preserve JSX equivalent. Or even HyperScript can be converted back to JSX is something looked at. All that being said still requires some amount of language support. This is the active discussion: github.com/solidjs/solid/discussio....

It's a tricky one though. TS was hard enough to support for language features. It still restricts what we can do with JSX to this day. I think at least in Solid's case the solution is making the JSX types more adaptable. If ReScript had the same sort of flexibility around JSX like TS does there would be no pause to support it.

Collapse
 
hoichi profile image
Sergey Samokhov

I'm not sure it's possible for ReScript compiler to leave JSX as is, for several reasons. For instance, at least from the typechecking perspective, every rescript-react component has a make function (that takes a props object) and a makeProps function with named arguments. Also bar in <Foo bar /> in ReScript is a shortcut for bar=bar, not for bar=true.

So I guess it all requires a bit of effort on the teams part. Here's hoping they're going to find time for it at some point. There is some interest, and I hope SolidJS gains some traction and the interest will only increase in the coming months and years.

Collapse
 
steakeye profile image
Andrew Keats

Svelte is extensible enough that if you wanted to, you could add support for ResCript via a preprocessor: svelte.dev/docs#svelte_preprocess.

Collapse
 
ryansolid profile image
Ryan Carniato

Yeah mind you does this work in the rest of the template? I read this as a way to process blocks. I know like Riot and Knockout used to also support setting the language in the template. Like in the expressions but on quick read I didn't see that.

I imagine it is possible for JavaScript based framework to import Rescript files and if they aren't working on custom Single File Component formats then they can get the full power of it without any preprocessor. But getting the syntax inside the template I think is the more interesting challenge. JSX feels like it could be that bridge with the right support.

Collapse
 
steakeye profile image
Andrew Keats • Edited

Or an alternative approach is to import external res files into your svelte components: github.com/sabinbajracharya/Svelte...

Thread Thread
 
hoichi profile image
Sergey Samokhov • Edited

That's always a possibity. You can even generate TypeScript types from ReScript. I was also thinking of using ReScript for domain logic and TypeScript for (React) JSX, because TypeScript has less ceremony for conditional rendering. But that scenario is not perfect. For one thing, if ReScript is your language of choice, not being able to use it in your views is not much better than just using templates with a DSL for loops and conditions. No big deal, but I'm already spoiled by the flexitibily of JSX. Also, having to compile (or at least typecheck) both ReScript and TypeScript means maintaining more dependencies. Also, TypeScirpt error messages are kinda meh. Also, context switching. So, all things being equal, I think I'd prefer to use less languages.

Collapse
 
mrjjwright profile image
John Wright

I always learn from your posts, thank you for continuing to contrast and compare approaches and libraries. For those of us who don't write libraries, but consume them, it helps us to think like the library creator and understand why decisions were made and avoid silly mistakes.

Collapse
 
december1981 profile image
Stephen Brown

What do you think about eg Rust+WASM?

Collapse
 
ryansolid profile image
Ryan Carniato • Edited

One day there probably will be something really powerful there. By that time will JavaScript be even more ubiquitous, and the reasons justifying it need to be greater? Maybe.

I think one of the interesting things is how much goes into what I describe in the article on the JavaScript side of things. I do a lot of benchmarking and we all know that hand optimized vanilla code is going to be the fastest. Rust+WASM has been closing the gap to the point now it is in dead heat in a JS targeted benchmark like the JS Frameworks Benchmark with a library like Solid.

However, that is low level vanilla code. We all acknowledge there there are more unlocks for WASM so I expect the gap to disappear with Vanilla JS and maybe even be quicker one day. However, the fastest WASM declarative libraries are much slower. Even ones using fine-grained reactivity. Now a portion of that is the same overhead I was referring to before that will be going away, but how much of it is because in JavaScript the template code we output doesn't even necessarily resemble what we input. We've added a layer to compile away the declarative code into more performant optimized code. By comparison I wonder how much longer before things built in Rust will follow suit. Will they ever be so inclined?

Size is also a real consideration in the browser. Every WASM solution I've seen is significantly larger. Maybe comparable to the larger JS frameworks like Angular or Ember but compared to say Svelte or HyperApp they seem monstrous. Something has to change in the way we consume/architect websites for this to be a reality.

So I think right now WASM delegated to special purpose things where high performance is necessary. Places where you can defer loading. Can we break free of that? Not sure. I watch WASM with great interest, but for different reasons. It seems as likely or more likely we see more performant server code written in JavaScript(TypeScript) than we get from Node today. Deno hints at it but I'm not sure that is the end of the story. Serverless WASM binaries seem pretty attractive as a deployment artifact for ecosystem flooded with JavaScript users.

EDIT: Speak of the devil this was posted today: bytecodealliance.org/articles/maki...

Collapse
 
december1981 profile image
Stephen Brown

Thanks for the very comprehensive response, and link. I didn't fully appreciate the issues with size, either.

Collapse
 
drsensor profile image
૮༼⚆︿⚆༽つ

What do you think about framework that mostly render in webgl/webgpu?
(e.g Flutter, PCUI, ...)

Thread Thread
 
ryansolid profile image
Ryan Carniato

I mean as long as the devices support them (which I imagine they do) there is a clear performance benefit here. I think there is concern that any work in this way to do general UI would involve basically re-inventing the core interaction points of the browser that we are used to. Things like accessibility etc.. I imagine any approach to do this in a general way basically would be building a DOM on top these technologies. You want declarative UIs etc... I think the biggest gap for them might simply being that they aren't the native implementation so there is always more work or code needed to run these. It is possible albeit unlikely at this point that a different standard could immerge.

I wanted to do some benchmarking with Flutter but the abstraction makes it hard to do apples to apples comparisons except with different versions of Flutter itself.

Collapse
 
kigiri profile image
Clément

Hey @ryansolid just wanted to thank you for all your write up on frameworks, I read all of them and learn a lot every time, I never comment but wanted to say thanks !

Collapse
 
swyx profile image
swyx

thanks for the shoutout Ryan! yeah i agree that the next frontier is whole-app compilation. this is ironically something that only React is even starting to think about with Server Components.

Collapse
 
ryansolid profile image
Ryan Carniato

Yeah that article came out shortly after I joined the Marko team, and having not being subject to it I was like, well there is always JSX. But seriously once I started working on Marko so much of it comes down to the language, IDE support, formatting, templating hints and errors. It's so much about building that experience.

Whole app compilation is something the Marko team at eBay was looking into the past couple years and why I was so excited to join up. It might be a lesser known framework/player but it has been great working through these sort of problems and coming up with solutions. We've been creating a system for cross module analysis that we've been using to inform compilation and are ironing out using it to do compile away reactivity similar to what Svelte does on a per file basis.

What is really interesting to me is different projects seem to be working on different parts of it to see what works. There is React Server Components. There is Astro, probably the first to get progressive hydration working on top of islands. Things like Prism have optimized localized compilation and hydration better than I've seen anywhere else. Even projects like Builder.io's Qwik which are less on compilation but more on the mechanical aspects of ultra granular progressive hydration, being built by both the creators of Angular and Stencil who left those projects to develop this.

It's crazy to think this far in things are still developing at this rate. But this is why I love web dev.

Collapse
 
cjsmocjsmo profile image
Charlie J Smotherman

I agree compilers are the future. Nice read very informative.

Collapse
 
chrisczopp profile image
chris-czopp • Edited

Same here. I think Virtual DOM is a nice episode which gave foundation (it popularised) for declarative UI development. Since there are already build-time diffing tools, we have a proof it can be done. And since we transpile our JS/TS anyway, it feels obvious to expect the tools to spit out the most performant code that doesn't require any runtime housekeeping like DOM diffing.

Obviously, it's more complex and there are times when runtime diffing can be useful e.g. rendering dynamically generated code in web based code editors. And I don't know how it's in Svelte, but Solid comes up with HyperScript version which gives that "edge-case" alternative.