SPAs are way too much work
Tags: javascript, webdev, discuss
Published: 2019-06-19 18:08:41


There is a lot of beauty in a simple HTML + CSS application with a sprinkle of Javascript mixed in.

I'll cover some points I like about this system.

## Speed
The HTML that gets sent to your user is the actual content of that page.

#### Consider Most SPAs

1. I load the page from the server.
2. I must download all the JS
3. I'm shown a loader while the JS fetches the data for the page
4. The virtual DOM is created and put into the Real DOM
5. The Browser renders the page

That's a lot of steps and it takes non negligible amount processing power to do. It can be a nightmare on mobile phones.

#### Consider SSR pages

1. I load the page from the server.
2. The browser renders the page
3. If done well, The javascript is loaded

In the SSR case we get the first render quicker and with much less work on the user's device.

With the added benefit of: The content we wanted the user to see is shown, regardless of our Javascript status.

Of course you can pre-render react and other SPA technologies but I'll get to that.

## The Sprinkles 

Now we can get to the fun part, the JavaScript! I love JavaScript. I love to write it. I love writing SPAs as well. However, we can rely on it a bit too much in some cases.

So how do you sprinkle in JavaScript? You could just use JQuery or plain JavaScript, but believe it or not there is at least one framework made for this: [Stimulusjs](https://stimulusjs.org/handbook/introduction). It's made to add functionality to the HTML you already have. 

I won't go into details about it too much but it's an _incredibly_ simple, and easy to learn framework. It also doesn't do too much. Basically giving you an easy way to attach to your HTML.

Now you can add your sprinkles. We use it for submitting forms and activating modals etc.

## Better flow

If you have designers that know HTML and CSS they can create mockups in HTML instead of photoshop. What this allows is an easy path from designer HTML to HTML template.

Because now that your HTML and CSS are taken care of you don't need to convert it to React. The markup is done! You just have to basically annotate the HTML with your templating language.

If something needs to be changed, at the end of the day it's just HTML your designers can edit the files themselves for tweaks. 

This is one of the big ways I think plain HTML beats Server Side Rendered React or Vue. (Although Vue is pretty neat).

## Mobile apps

If you see how [Basecamp creates their mobile apps](https://m.signalvnoise.com/basecamp-3-for-ios-hybrid-architecture/) SSR and plain HTML is a big key to moving fast with small teams. 
You can load the plain HTML page in your app and augment it with Native components. It's way lighter weight and easier to update than React Native. Having used React Native I wouldn't actually wish it on anyway ;) As long as your pages are mobile optimized you have the foundation for a mobile app. You are always just using the same markup.

What do you think?

## When do I use React?

There are places React makes sense. Things with heavy data and reactivity (hehe) can really benefit from it. An online image editor or a video site like YouTube and Hulu. 

Instead of an entire site SPA we can augment parts of our site with React. Take our video site example. Maybe we only want to load React on the video page but still just SSR the other listing pages.

On the video page our JavaScript sprinkles can load in the React code. Code splitting in Webpack works great for this!

Here's an example using stimulus

```javascript
//Video React Loader controller

export default class extends Controller {
	static targets = ["react"]
	intialize(){
		this.videoJS = import("./video.js");
	}
	connect(){
		const reactParent = this.reactTarget;
		
		this.videoJS.init(reactParent);
	}
	disconnect(){
		const reactParent = this.reactTarget;
		this.videoJS.destroy(reactParent);
	}
}
```

```javascript
// Video.js
import VideoStuff from "./whatever"

function init(node){
	return ReactDom.render(<VideoStuff />, node);
}

Function destroy(node){
	return ReactDom.unmountComponentAtNode(node);
}
```

```html
//video.html
<div data-controller="video">
	<div data-target="video.react"></div>
</div>
```

This way we only load React when we need to and can still SSR render all the other things we want.

What do you think?