The place where random ideas get written down and lost in time.

2025-10-16 - Web SPA: Flutter vs React, JavaScript vs TypeScript

Category DEV

Recently I've completed a number of small dynamic website projects, and I want to discuss my view on the way to choose to implement these sites.

This is to be read as an opinionated essay. YMMV.

SPA, a Single Page Application

Here are a few sites I completed recently:

They all have in common that they are “Single Page Application” websites. What does that even mean? In short, that means it’s a single HTML web page that uses JavaScript to implement a “full” web site by simulating several pages.

Let’s take an example: we want to create a small e-commerce site. We'll structure our site as different pages, each rendered by their own HTML file:

  • http://example.org/mysite/index.html    -- the main entry point
  • http://example.org/mysite/about.html    -- a page “about this company”
  • http://example.org/mysite/catalog.html  -- the catalog browser
  • http://example.org/mysite/product.html  -- a page detailing a single product
  • http://example.org/mysite/purchase.html -- the purchase form

Instead an SPA web site uses a single file:

  • http://example.org/mysite/index.html    -- the sole page of the web site

However, using JavaScript, we’ll change the content of the page to simulate showing the “about” page vs the “catalog” page, etc. One way to know which one to render is to encode the desired “page” using the hash portion of the URL:

  • http://example.org/mysite/index.html
  • http://example.org/mysite/index.html#about
  • http://example.org/mysite/index.html#catalog
  • http://example.org/mysite/index.html#product/{id}
  • http://example.org/mysite/index.html#purchase

From the web browser point of view, it's always the same page being rendered (index.html) yet JavaScript is used to read the hash name and decide how to fill the page -- when the page loads, we use JavaScript to literally inject the content we want in the web page at runtime. If you were to read the “source” of the main index.html, you’d find it basically empty (or more exactly having just a single div container).

The mechanism above using the hash is called a “hash router”. There are other ways to do it, that's just the one I prefer.

I want to emphasize that the web site loaded by the Web browser due not user HTML pages the regular way. What the browser loads is a large JavaScript file that generates all the elements on the page dynamically using code when the page loads. For example, to display a label and button, we'll have JavaScript code using the DOM API document.createElement("button"), then manually set the attributes, etc. Rinse and repeat for every single HTML entity on the page. That would quickly become unbearable, wouldn't it be nice if instead we had some kind of tool that could parse a template and generate all that code for us? The template could even look like familiar HTML!

It’s all about the frameworks

In this kind of web app, we rarely write “vanilla Javascript” (e.g. “code everything by hand”). It’s just too tedious. Instead we use a framework to help us write the web page. There are a ton of frameworks out there, but essentially there are 4 that I consider the most popular and important:

  • React JS, with code written in JavaScript or TypeScript.
  • Angular JS.
  • Vue JS, with code written in JavaScript or TypeScript.
  • Flutter, with code written in Dart.

I believe that also more or less represents their level of popularity. My opinion on them, in a one line summary each:

  • Flutter is my favourite one, but… We’ll discuss the “but” later.
  • React JS. I started that way, and honestly I hated it. Ironically it’s only after switching to Flutter that I finally properly understood React.
  • Vue JS. I tried this one for the sake of trying it. It’s said to be more approachable when starting than React. I can see why. Still I’d prefer React for the long run.
  • Angular is a mastodon. It’s made to build large sites that scale. It’s a very complex framework, and it seems like it would scale very well. But for a single little SPA, it’s totally overkill IMHO.

Languages: JavaScript, TypeScript, and Dart

React, Vue, and Angular can equally be coded using JavaScript ES6, or TypeScript. In my option, JavaScript is always the wrong choice, no matter what the question is. Period. It’s an absolutely terrible language. Yes we can hand-code it without a compiler, and yes it runs directly in any web browser. Well, mostly. But it’s kind of like flying without a net. Working with JavaScript is trying to admit that “hope is a strategy”. It’s not. Kids, just learn to say no to JavaScript.

TypeScript is the “sanity” version of JavaScript. It forces us to use a compiler (since it compiles to JavaScript after all). My first reaction against TypeScript was why would I have to use a compiler toolchain? “It’s too much work”. But actually that’s a good thing -- the compiler does a lot of checking for us -- the tool is here to help us. It forces us to understand the types we’re using -- as the name of the language implies, it’s JavaScript with actual types, not just “whatever I can randomly put in a variable and hope it’s the right thing.”

The only drawback of TypeScript is that it’s essentially “JavaScript with lipstick.” Nothing prevents us from doing all the crappy things that JS allows us to do. However, TypeScript comes with a linter tool which tries to catch us on exactly the common mistakes that everybody makes. Don’t ignore the warnings, they are here to help us.

Flutter is coded in Dart. That’s its strength. That’s also its main hindrance. We have to be willing and make the jump to learn one more language just to write that small SPA thingy. That actually has dragged me down, and I avoided Flutter for a long time just because of that.

But… once I jumped into it, I realized that the TL;DR for Dart is “Java meets TypeScript”. Seriously. And if, like me, you find the Java syntax to be actually quite agreable, then Dart almost becomes “TypeScript as it should have been from the beginning”. In essence, it was intuitive, easy to learn, and easy to get back into it when looking at old code.

Flutter

I'm not going to try to give you a coding example of a Flutter app here - there are many examples out there already. Instead I'll try to explain why I liked it.

One thing you need to know upfront is that Flutter does not pretend to be a web framework. It is first and foremost a cross platform toolkit designed to create apps for mobile, web, and desktop.

As such, it will look foreign and weird to an HTML designer. We're not coding an HTML app with div and span and CSS. Not at all. We're coding screens using views (named widgets) and layout managers. Exactly like we would do in Java AWT or the Android view system. So if you come from Android or AWT, the layout system is fairly self explanatory.

Flutter has so-called “Stateful Widgets” and “Stateless Widgets”. They do exactly what the name says: a stateless widget is one that never changes (e.g. a title), whereas a stateful widget is one that changes with data in the application (e.g. a cart item count, etc). It’s brutally efficient and clear.

Flutter has its own ecosystem of third party libraries one can include. This isn’t NPM, but close enough. Everytime I wondered “did someone write a library doing X”, there was one. There’s also a unit test system that works fine and without drama.

React JS

React is both the grandaddy and the poster child of, well, the reactive SPA design. It works fairly well yet at first glance, I found it at the same time easy to understand yet confusing and clunky.

Like Flutter, in React we code screens using “components” (same as Flutter Widgets). However we compose and create layouts using regular HTML and CSS positioning, all intermixed with TypeScript code in what is called a JSX template. In this case, the layout system will feel familiar to anyone who has done their share of web design, and the template mixing code and HTML reminds me furiously of PHP (without the head trauma of the PHP language).

React also has stateless vs stateful components. However that’s where it feels clunky and smells like legacy: there are no clear classes to inherit from, one just calls “useEffect / useState” methods in a component and that makes a component reactive. They are “hooks” and it feels bolted on after the fact.

When I first learned React JS, that totally confused me. Ironically, it’s only after learning Flutter that the React JS stuff started making sense. And I’m still easily confused by e.g. the “useEffect” dependency lists.

My last 2 projects used React JS. I decided to standardize on that.

Vue JS

Vue is the last one I tried. Every comment I read around emphasizes that Vue is very beginner friendly. The expected cycle is to learn basically Vanilla JS, move to Vue, and maybe move to React. I went directly from JS to React years ago, so I wanted to understand what Vue provides.

I’d oversimplify by saying that Vue and React are mostly the same thing, except they take literally opposite directions when it comes to generating content.

In React, as in Flutter, components/widgets are classes which are called and generate the UI using function calls. Literally a render method is a function that has code stating “hey place a div here, and in that div write a button, and label, etc.” If you want a table with multiple rows, the render method will literally have a for loop generating each “<tr>” element.

In Vue, the rendering is done by having an HTML piece of code directly in the file, that has placeholder variables, and a separate “script” code that computes the values for each placeholder variable. In a sense, that’s template rendering instead of generating code.

I’d say the Vue approach is more web designer-first, whereas the React/Flutter approach is more coder-first.

I can see the direct benefits here. I agree that Vue is likely more beginner friendly, especially for anyone who’s used to hand-design web pages.

However I think I’d go even further: the Vue approach forces you to split the template content from the code. In React, a newbie is going to be tempted to mix them in a very messy way -- I structure my React code in a top-down component way now, but when I look back at my first React apps, it was a whole mess with little separation of concern. The additional Vue constraint of script vs template is going to help beginners avoid that mess.


  Generated on 2025-11-27 by Rig4j 0.1-Exp-b292492