loading...
DropConfig

SPAs are way too much work

powerc9000 profile image Clay Murray ・3 min read

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. 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 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

//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);
    }
}
// Video.js
import VideoStuff from "./whatever"

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

Function destroy(node){
    return ReactDom.unmountComponentAtNode(node);
}
//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?

Posted on by:

powerc9000 profile

Clay Murray

@powerc9000

I like programming and typically video games too! Working on games and stuff. They/Them

DropConfig

Verizon control and hosting for your config files. https://www.dropconfig.com

Discussion

markdown guide
 

It certainly depends what you're doing with it. When I'm building something small I never want to go through the effort of setting up something like Vue or React, as in small projects I think the downsides often outweigh the ups.

That being said, I have 2 big reasons I like them. One is they keep the frontend and the backend separate which is nice sometimes. Especially in big projects, I prefer to keep the clients separate from the server-side. It also means if I have someone helping me who is not familiar with the backend languages/services, they can still easily work on the frontend, requiring nothing more than API documentation.

The other reason is in a lot of my projects I like providing an API that is accessible from mobile apps, discord bots, etc. If I build something serverside rendered it often means I then need to build API endpoints separately to provide the same services. If my whole backend is an API from the start, it makes it easier to stick any number of clients on top of it, whether they be mobile, web or other services.

Really depends on what you're doing. I wouldn't use them for small projects or anything where an API is generally unnecessary. But certainly useful for very large projects or anything where you're going to have a lot of clients attached to the one backend service.

 

Well i think you have good points. I agree on the having APIs part but i usually do server side rendering and it just consumes the APIs.

And working with other people isn't hard because at least for me. I use ejs. So the templates are pure js as well. And the frontend people can do whatever they like as long as the server can return it.

 

Would you have a separate serverside project that consumes the API or just abstract it in such a way that the SSR and the API endpoints call the same services in your code?

Usually, when I think of SSR I think of templating (An example is my personal site, written with ASP.net Core and Razor templating. No API's are present there and the front-end is part of the back-end code in that it uses ASP's templating engine).

Just curious how you would usually go about it!

So what we currently do is yeah if I want to get all the documents I have a model for the documents API uses at GET /documents/{id} uses and the view uses.

The views are ejs templates. The frontend is part of the backend code but the way its set up it's in its own folder and has its own build process with parceljs.

So it's a big ol monorepo basically.

 

I fixed SSR pages for you:

  • I load the page from the server.
  • The browser renders the initial page (usually some kind of a spinner)
  • I load all the css and JS
  • The JS fetched all the data from the server
  • The javascript hydrates the dom with the data from the server
  • The browser has to render the updated DOM

:D

But seriously, the benefit from SPAs is not speed but the amount of downloaded data. About 95% of your page can be cached and reused, the JS will only download a small piece of data to check for possible updates, and update the dynamic content of your page.

 

And I do get the benefits but I just think SPAs are heavy especially on inital load. Plus A JSON payload isn't that much smaller than just sending the HTML page of it. We also use turbolinks so we still get the caching etc. Of the page while sending back pure HTML.

And I think whatever you gain in "speed" you can lose in productivity. I think SPAs are actually really great for large teams as well. Where you have a frontend team and backend team and they don't have to collab at all.

But when you are just a single developer or just a few having SSR apps can save you a lot of time.

 

I guess if you want to replace entire page content, and you've got to download it from the server then sure, you'll have to download a lot of data (about 80% - 90% if your entire page) because the actual content is what weights the most. Devdocs does a very good job at saving downloaded pages in IndexedDB for later access.

When it comes to productivity, I guess it comes to everyone's individual experience with them. I actually found SPAs faster to make than SSRs, but then again, I REALLY enjoy making websites in React, so my point of view might be a little biased.

 

SPAs maintain state of Html Page, SSR unnecessary cause entire page to reload and user feels lost as many things on page changes, especially the scroll position !! And SPA is called (Single Page Application) the word Application implies it is for an active application where user interacts and performs an activity. SSR is only useful for SEO and applications don't need SEO because most applications will always require an authenticated session.

 

Well that's what turbolinks is for. Loads the entire webpage in the background and merges it with the current one. I don't see your point about many things on the page changing. If I go to a new page isn't that expected? And shouldn't the scroll position go to the top of a new page? Plus a pretty big web app, GitHub, uses many of the techniques I'm talking about.