Hacker News new | past | comments | ask | show | jobs | submit login
You probably don't need a single-page app (plausible.io)
816 points by ukutaht on Feb 17, 2019 | hide | past | favorite | 499 comments

This. So much this.

My company (4,500+ people) ordered all products in their portfolio (~12 web apps) to migrate to SPA front ends about a year ago as a way to stand out from our competitors, and boy has it been painful.

Prior to that initiative, we had been using the hybrid approach mentioned in this piece, embedding SPAs only where necessary and sticking to SSR everywhere else, which worked really well.

Since the announcement, our productivity has diminished dramatically since so much of our time is now focused on re-working functionality that already exists into an SPA, and it's completely unnecessary. Not only that, but extending these UIs will take more time in the future than their SSR versions due to the added complexity of the front end frameworks, and we're definitely going to make mistakes along the way that we weren't making before.

It drives me crazy to think that some exec came up with SPA-ing everything as a sales pitch to clients, when 99.9% of our clients have no idea what an SPA is. And the amount of money being spent on turning already-working apps into SPAs is astronomical.

Wow... that is just insane.

I've been working alone for so long I've not had to deal with anything like that for years, but I'll offer this...

Doesn't matter, so don't let it matter to you.

When I worked for others I'd offer my opinion and advice and when it was ignored I'd do it their way every step of the way because it really does not matter. You get paid the same either way.

I'll add that because it didn't matter to me I ended up getting to work on some pretty cool stuff. Everyone knew I wouldn't whine about changing directions or being taken off a project and jumping on whatever they wanted so I was almost always the 1st choice to work on something new.

When that happened I was often able to influence the direction of the work.

Yes. This... yes.

All you can do as a professional, with experience, is offer up an argument and attempt to make it convincing enough to compel people to do things your way. If they reject your option, defend only once, and no more. After that, simply step back and work with whatever technologies are decided upon.

You can also attempt to work the social networking game and play (internal) politics. If you do these successfully you're more likely to get your ideas heard and implemented. I find this tiresome.

Ultimately if I'm being polite, professional and basing my arguments on facts and evidence, and they're being rejected, I'm not expelling any more energy on this front. Move on. Work on and with what's decided and have fun doing it.

> work with whatever technologies are decided upon.

It may sound great when you learn something new, but when you worked with a technology and you know its deprecated crap - as a professional - you should also consider your own career..

Work on crap nobody uses for 5 years and you are so handicapped by that you "will" find a new job, but rather not a good one.

Not everyone can spend hours at home to keep up with the industry.

That's true, but not really the same thing.

I was looking for work once and went to place that made wheelchair lifts for vans and buses. There was a miscommunication about what they were hiring for and when I got there they took me out to a drill press with a stack of thousands of parts on carts that needed a hole drilled in them.

I politely declined the position.

> My company (4,500+ people) ordered all products in their portfolio (~12 web apps) to migrate to SPA front ends about a year ago as a way to stand out from our competitors, and boy has it been painful.

This doesn't seem like a problem of "MVC vs SPA".

The same problem would occur if you were ordered to rebuild 12 apps written in Rails ( or whatever full-stack MVC framework) in a different one, like Django, for example. You'd experience the same pain.

The story of rewriting Netscape comes to mind and a few others. Point being, not much value in rewriting something that works in different language.

You overlooked this part:

> Not only that, but extending these UIs will take more time in the future than their SSR versions due to the added complexity of the front end frameworks

You simply trade back-end frameworks complexities for the front-end framework complexities. With the right architecture there is no huge difference IMO, just of course you also need to upgrade your teams so that they can handle a lot more tasks on the front-end than with SSRs (and you'll probably need less back-end devs)

Front-end frameworks have a way of going in and out of fashion / support much faster than backend ones.

There was indeed a moment few years ago when front-end frameworks/libs were changing at warp speed, but last year or so I think the situation crystalized a lot. You now have React and Vue as major players and Angular competing for the 3rd place against some fresh libs... and I don't see that changing anytime soon.

yeah, you have React, but which of the 30 fashionable state-management libraries are you using? Typescript or Flow? What version of JS syntax? What compiler what minifier? oh hey, half of these just stopped being maintained without warning

Every year this is said like burning man is dead.

I predict a bigger react ecosystem. The slide of vue but the raise of the Quasar framework for apps. The rise of Angular once again.

I have always felt as angular was the second major player and vue the one in the 3rd place.

It's possible, especially if you look primarily at the enterprise market. From where I stand (startups, SMEs) it seems like a lot of people moved from Angular 1.x directly to Vue, skipping Angular 2+ versions. I haven't been offered any Angular projects in about 2 years, while React and Vue are really popular. But it's just my perspective, global situation might be different.

This has also been my experience. Enterprise systems really went all-in on Angular 1 for some reason (I personally suspect because it bridges reactive and MVC), and when it was time to move to a fully-reactive front-end framework, in my opinion Vue and Angular 1 are similar to each other in a way that React is not similar in relation to either of them or Angular 2+.

I still can't quite put my finger on why Angular 1 and Vue rhyme, though. It's common wisdom that "If you know Angular, you'll pick up Vue quickly", and it seems to be true, but nobody has ever explained to me why. Is it the state management? Reliance on viewmodels? How they're more complete systems out of the box and can be reasoned about holistically? Help a girl out, HN.

Not only that but you have to reinvent SSR with front end frameworks. Why do something simple when you can make it 10x as hard but ultimately end up with the same result.

I mean, I think these SSR front-end frameworks are a pile of crap, not worth the added complexity, and I hate using them; but it's pretty clearly not the same result. The problem they're solving is not "render on the server side", it's "render on the server side for the initial load then inject a fully functioning SPA for subsequent loads".

I'd rephrase: Front-end frameworks have been progressing through an iterative process, browsers are adopting standards that make them more consistent, and the tooling have been advancing at a rapid rate.

FE is a vibrant ecosystem and the tooling, in my opinion, is some of the best I have worked with as a SE.

Not at all, people moves between libraries of the same framework, they will likely refactor jQuery mess into a framework, but it's unlikely for a team to move from React to Vue or Angular (and vice versa).

you don't have to follow every trend. stick to one framework until it is no longer suitable. since 2012 i have learned to work with exactly two frameworks. i started with angular 1, and switched to aurelia when angular 1 was no longer viable. i'll stick with aurelia until it has run its course.

Yes, but front-end developers are much more fungible as well.

Not if you've built your product around a front-end framework that's gone out of style.

Remote workers are good for this scenario. My current employer is maintaining an outdated backbone.js app, thankfully I'm not on that team.

We have one guy in the office responsible for all of it, as warm bodies with backbone experience are impossible to find. However, should we decide to employ remote workers, we can easily find developers with backbone.js experience from Romania, Lithuania, India, and Pakistan who would work for a pittance and be grateful for the opportunity.

Also, on the majority of SPA frameworks you have the notion of components which makes making the UI a lot simpler than with traditional SSR abstractions (templating and partials are not sufficient).

Or your backend template engine is weak. In Elixir, EEx used in Phoenix, every template is a function. It's not supper good, but it's component (I hate term "component" and prefer "function")

But a component is a function that satisfies certain properties, why would you prefer to not to be precise in your communication? Do you call squares rectangles because you hate the term "squares"?

In my example, it's very precise that a template _is_ definitely a function. And conceptually I still think of it as function.

For your example I'd call it "squares" not because I don't hate it, but I don't think squares has something to do with "component"

The complexities of back-end frameworks are far less than the complexities of front-end frameworks in my experience and observation (in particular because the latter tend to needlessly reinvent half of a web browser). Additionally, the back-end complexities still exist when using front-end frameworks (unless you don't actually have a back-end, of course).

"You simply trade back-end frameworks complexities for the front-end framework complexities"

Not necessarily, you can have simple and modular front-ends while also having less complex back-end frameworks. The question is between SPA and non-SPA web applications, not between SPA and JSP/PHP.

Is there any possibility that the added complexity is a symptom of the framework in use and not a general problem with ALL frameworks? I know I've experienced many projects and found server side rendering more complex then client side when using frameworks like Ember.js.

I'm a front-end engineer, but I'd agree that SPAs are always more complicated than a pure SSR solution: You're inherently doing more. You're probably already tracking state somewhere on the backend (e.g. in a database). An SPA means you now have to track state on the front-end too.

There are benefits and things you can do with an SPA that you can't do with pure SSR, but they _do_ come at a cost. TANSTAAFL.

TANSTAAFL stands for: There ain't no such thing as a free lunch

But I agree, that seems to be my impression. Single Page Apps allow higher quality User Interfaces (if done right), though they do require more work.

It's a symptom of the SPA architecture. Since you give up a lot of basic functionality by not using multiple pages, that same functionality has to be reinvented.

That's pretty debatable. I've worked on some gnarly SSR architectures and making changes to the front end almost always involves refactoring some of the backend as well.

But this claim is simply wrong in a large percentage of cases (at least among the “web application” projects I have seen firsthand).

Yeah, I don't buy that. React and Vue are dead simple.

React and Vue are dead simple.

But if the comparison is with more traditional SSR sites, React and Vue are also not doing everything the back-end was doing before.

When you talk about React and Vue it should mean React ecosystem or Vue ecosystem, not view layer. Then noting is simple.

I don’t disagree here at all, but I would note that generally server side templating is often a mish mash of business logic, view logic, accessing query string and session parameters, and whatever server side Singleton/globals available in the template context, that becomes horrific spaghetti in no time at all.

Compared to client side rendering discrete web requests with minimal templates; you usually get much better separation of logic, view, and code than the typical serverside solution.

There is a happy medium where server side services are encapsulated to separate concerns in a similar manner, but it rarely happens, even with competent, experienced, well intentioned teams.

SPA doesn’t guarantee good separation of concerns though. I have seen many a horrible SPA in my day that had all the business logic in the client side JS and zero validation server side. Server basically a very thin wrapper around the database.

I’ve been doing this for 15 years, and if I’ve learned anything it’s that developers can figure out ways to abuse anything.

Separate frontend from backend development and make it even two teams. This makes it much more robust and loosely coupled because both sides protect the interface from each other.

My experience is the opposite. The interface created in such a situation is the worst of both worlds.

This works. Now you only need double the engineers to create the same app as you would using a server side framework. Hardly a more powerful argument against SPAs than this.

I'm not sure I buy this. I recently worked on a project where we had one .net core developer, a dev ops guy, and me doing the client SPA. We were all able to focus on our core competencies and turn around the project incredibly quickly. I would argue that you can get away with the same team size split between front and back end and possibly end up with a more efficient allocation of resources.

Perhaps, but if both teams are half the size, specialised and deliver faster, it’s a win.

That may not always be the case, but if your SSR team and API team are the same size, your devs suck, bluntly. API based backends are much easier to build, test, manage and look after.

Two teams sharing an interface means one team will block the other most of the time if a new feature always requires changes in the interface and implementation on both sides. Doesn't matter if individual development speed increases, overall project speed will suffer greatly.

That's a hell of a generalisation, and it falls down pretty fast when you move beyond CRUD apps. You can easily end up with entire teams whose role is just to babysit Elasticsearch.

No, it doesn’t.

Regardless of the backend stack, if you maintain both the front end and the backend, it is categorically less effort to only maintain the backend (ie. just run an API).

Half as much effort? 3/4? I don’t know, maybe your UI is a man autogenerated swagger frontend and it’s (43/50) as much effort.

It depends... but it is always less effort not maintaining an external user facing UI.

I think the counterpoint to this would be Google Search. The core product is incredibly simple from a frontend perspective, but the backend is world-class engineering.

I think making information usable is hard. This means that the burden of the development falls on whatever is making the information useful. If you simply can query an API and get stuff back that's valuable because the data is already processed, UI is pretty easy (aka Google). If your backend is returning raw data that needs to be organized and displayed, and users need to be guided through complex processes that are just simple CRUD operations server side, you have a much harder UX/UI challenge. Most things fall somewhere in the middle.

Well, what does your API actually do? If you're e.g. Heroku, your front end does almost nothing in comparison to the rest of your product. Why would running the backend of a globally distributed infrastructure-as-a-service company be easier than maintaining the front end?

I'd argue more than double considering all the things a good SSR gives you reliably for free.

This is a load of nonsense.

If you can't separate concerns in a hybrid MVC pattern, you'll be screwing it up just as much in an SPA.

Plus you've got the extra layer of an API to maintain too making it even more complicated, and more likely to spaghettifi, not less.

>Plus you've got the extra layer of an API to maintain too

On the other hand, if you're providing a service that will always have an API, and you want to make sure that all the functionality you provide is nicely accessible through the API, building the frontend on top of it can be a good approach. The developers at the company I work for have done this, and IMO it's worked out pretty well.

Possibly, though your perfect API design may differ significantly from your perfect site structure. It feels reasonable to consider both and see it as a positive if the use cases work.

Nonsense. People have been doing that for years before the single-page hype. The servers generating HTML contents use the API as their own backend and you have better layering.

Are you sure about that? Today I think this is a good model, but I haven't seen it in the wild before.

This is also the main argument that keeps me on the side of SPA for our own project, at the moment. Our product is a specialized database with a fancy GUI on top, but we have customers that only use the database through its API; by using it ourselves for our frontends we make sure everything is doable that way.

The other argument is that frontend developers are looking for SPA work because they see SPA work everywhere. There's an element of everybody having to go with the flow...

I definitely view being forced to build a sane API as one of the perks of a SPA. Having worked on some PHP pages with SQL queries, HTML, CSS, & JS all in a single file you would be surprised how people fail to separate concerns when they aren't forced to.

How would you make it "even more complicated, and more likely to spaghettifi" to maintain an API than having to maintain a rich UI. Now that's a load of nonsense, or at least very misguided hyperbole.

It doesn't often happen because of Conway's law - that "organizations which design systems ... are constrained to produce designs which are copies of the communication structures of these organizations."

Its always possible to architect the web/app back end to do everything through APIs, keeping the APIs pure, and ensuring that others will be able to build UIs on top of them.

But in many organizations the same people that own the APIs also own the back end. That means it takes discipline and an acceptance of extra costs to keep this separation. Its easiest and cheapest to just slop all the back end together.

With an SPA, a different team builds the front end from the back end, and APIs are the only way for them to talk. That acts as a force for good APIs.

IMO it's one of the long-term failures of web architecture for CRUD that there isn't a unified solution for this; not only should they be the same team but they should be in the same repo, quite possibly in the same language, and the number of places a field has to be defined should be as small as possible. Let the machine sort out separation of concerns and what code goes where. Learn something from dBase and FoxPro.

Apologies if I misunderstood you, but isn't all of that criteria met by a Node/GraphQL/React app?

1. One language - JavaScript

2. One repo - containing a Node backend, also builds/serves a front end bundle (alternatively use Next.js/etc if SSR is your thing)

3. Use GraphQL schemas to handle your API(s) and consume the minimum necessary data on the client, reduce redundant field declarations

One language, one repo, easy & consistent API production/consumption, no?

I completely agree that a big part of this conversation falls on ensuring code quality is maintained over time, regardless of the architecture you choose.

Fortunately, I inherited a set of pretty well-maintained SSR rails apps, and they've been pretty straightforward to continue working on (with a couple of exceptions).

The single biggest disadvantage I see with front end apps is that comprehending state management via redux and co. is so complicated, and so, so easy to get wrong.

I can tell a coworker to refactor a smelly ERB view and extract out a new template, presenter, whatever. But redux still causes us problems that require refactors months later. It still feels way more cumbersome than being diligent about keeping controller/presenter/template logic clean. We're also far more competent rails developers than we are modern UI developers, and that definitely factors into our productivity.

The real issue here was that someone forced a bunch of developers to rewrite their entire product in a stack they don’t know, against their will.

Hi, I'm a Redux maintainer. Any specific concerns that I can help with?

You might want to check out our new Redux Starter Kit package. It includes utilities to simplify several common Redux use cases, including store setup, defining reducers, immutable update logic, and even creating entire "slices" of state at once:


After having some pretty extensive (heated) debates about the merits of redux here on HN, I've come to the opinion that the love/hate for redux is a consequence of the departure from MVC architectures that more experienced developers are accustomed to. There are decades of best practices built up around scaling object oriented MVC architectures, but react and redux come from a completely different school of programming where trying to apply traditional inheritance patterns is impossible and can mortally wound a project.

There was an article about entity component systems recently posted here, which are typically used in game programming, and I was shocked at how similar it is to the architectures I use in my react apps. This entry [0] from the ECS wiki is a good summary:

> Whereas in an inheritance-based design, an enemy may have a complex inheritance chain such as Damageable <- Actor <- GroundBasedActor <- Enemy <- ZombieEnemy, in a C/ES-based design you might have a Health component, a GroundBasedMovement component and a ZombieAi component added to an entity named ZombieEnemy. This eliminates ambiguity issues encountered in an inheritance-based design (should the root be Actor <- DamageableActor or Damageable <- Actor? Should items be implemented twice as PickupActors or DamageablePickupActors?). At the same time, components can be freely combined: a damageable inventory item? add the Collectable and Health components to an entity.

It occurred to me that in a lot of ways, games are just extremely complex user interfaces. So it makes sense that patterns that work well in game architectures should map rather cleanly to application UIs. I'd be interested in hearing if anyone else sees the correlation here, or if I'm just confused and misunderstanding ECS architectures. My email is in my user profile.

[0]: http://entity-systems.wikidot.com/

i love redux - surface area for bugs is reduced so much compared to the past. thanks!

> I would note that generally server side templating is often a mish mash of business logic

If you don't have good, experienced senior developers or they don't have discipline, yes. But that's true for any technology. Good developers have the knowledge for simple things like how to separate business logic from templates...

TBH if the thing is getting rewritten every two years because of $new_paradigm, code quality matters less.

It would be nice if, given a task, we could teach people to choose the right approach in code the first time, but given we still have trouble recognizing good developers, the fast-paced churn of rewriting apps is a decent hedge until we figure out how to train the people we want.

We seem to only want developers with this skill, but then force them to rewrite stuff often enough so that no actual long-term gains can be realized from their expertise.

> TBH if the thing is getting rewritten every two years because of $new_paradigm, code quality matters less.

I disagree with this. De-prioritizing code quality because a rewrite is on the horizon is a great way to paint yourself into a very bad corner.

Imagine letting your codebase rot with the assumption you're going to rewrite it only to have your CEO walk in one day and completely shift priorities to build some new feature to land a new customer or appease a current one (a not-too-different scenario happened to me once.)

Priorities change all the time, and quality code grants the flexibility to adapt to changing priorities.

Unknown: when random CEO idea occurs

Known: we’re definitely rewriting it in two years regardless of this CEO feature

The feature probably isn’t that complicated anyway

Maybe if you want code quality, stop rewriting so much shit because there’s some new hotness. Probably helps to not have so much new hotness too.

So I could see an issue with someone writing business logic in a view and then someone else rewriting that business logic somewhere else slightly differently.

But I've seen the same thing happen in the SPA. Where one person calculates some value in an API method, another doesn't know about it and calculates it again slightly differently in a different method leading to app inconsistencies. And SPA's make it worse not better because it sometimes forces you to write a piece of domain logic twice, once for the browser and once serverside.

I honestly don't know what's wrong with accessing query strings or session information. But I think maybe the reason you've seen template code using global state is because the template code was just written earlier back before that information had really soaked into the entire development community.

I could make the reverse argument: bad frontend programmers who dont use the facilities available to separate concerns create unmaintainable spaghetti when good backend programmers who separate concerns properly produce beautiful maintainable code.

The key being bad programmers dont isolate concerns and good ones do.

This separation of concerns is also good if you have both a web app and native mobile app. The server side ideally puts forth an API useful for both;

Our controllers use APIs. This was common before SPAs became all the rage.

Indeed, that's true. While I'm not saying they're good for everything, one thing I like about SPAs is that the server can just serve up an API that is usable by both web and mobile clients. No duplication of templating/view logic between server and client as often happens when the server is serving up HTML.

One reason the SSR mess is so easy to walk into is that everyone knows it's a reasonable amount of refactoring to get out of later. The cleanup of an SSR app lacks the deployment headaches of SPAs (doubly so with the service worker layer).

These problems appear largely academic to me.

Well, in our case moving from server side MVC to SPA approach has drastically increased productivity and stability of our applications.

MVC approach was a hairball of code where 2/3 was dealing with synchronization of state between client and server, and only 1/3 being related to actual application logic.

Clean separation of frontend SPA and backend API made both sides simpler and more robust.

I would also wholeheartedly recommend separating the development into two teams (frontend / backend) . It makes both pieces of the application even more robust due to both teams guarding the interface with the other part even better.

I turned around an SPA fast because I'm only a backend developer. I wrote API endpoints only and contracted a friend to write the frontend, delivering a swaggerspec and vague ideas of what I wanted. Completed the thing in like four design meetings and one touch-up meeting. Couldn't be happier.

> I would also wholeheartedly recommend separating the development into two teams (frontend / backend) . It makes both pieces of the application even more robust due to both teams guarding the interface with the other part even better.

In theory, we should strive for that. In practice, back-end team tend to strive on "technical purity" and would ask the front-end team to take any hacks/workarounds necessary to deliver "compelling" user-experience. One example would be the disagreement over "Data Model" of front-end vs back-end.

Hah. I just finished a huge refactor of an application where the back end developers "dramatically simplified" the business logic and architecture. What they meant is they removed all of the business logic from the back end so the client could do it instead. You might be able to tell I'm still a little bitter about that.

> In practice, back-end team tend to strive on "technical purity" and would ask the front-end team to take any hacks/workarounds necessary to deliver "compelling" user-experience.

The key is to design the DTOs (which API endpoints are based on) starting from the API consumer perspective. Business logic on backend is responsible to deal with mapping of DTOs to the domain models and in turn to data access layer models.

This results in most DTOs being "flat" and easy to consume by client.

This where technology like graphql can really shine.

You can do that separation either way. People working on state sync and actual apis should be different anyway (unless your team is small).

I'm not convinced. We were using MVC for years and tried different approaches, but the API code is incomparably cleaner when it doesn't deal with client concerns.

> Well, in our case moving from server side MVC to SPA approach has drastically increased productivity and stability of our applications.

It sound as though the application was a suitable candidate for an SPA and should have been developed as one to begin with?

It was not one application. Since we moved to SPA we have started multiple new applications having very different use cases.

Eh. The problems you talk about have little to do with SPAs in general, and have more to do with "rewriting things from A to B". If you had started out with SPAs first and wanted to un-SPA everything, you'd be making the same comments. The issues you mentioned aren't intrinsic to SPAs, they're intrinsic in redoing things.

You're right, but it's also intrinsic to the senselessly shifting paradigm/bandwagon-jumping around SPAs. It's not just that redoing things is a problem, but that the motivation behind the rehaul is poorly conceived.

I think that's how the cookie crumbles, unfortunately. Most companies want to be on the biggest bandwagon to ensure they have a steady supply of fresh, young employees. Few companies want to rely on niche software that only a few people know how to work with. As long as younger people keep jumping onto new trends, companies will continue to follow.

I'd love to hear some trench stories where these kinds of initiatives to increase the complexity of (what appear to be core) business tools were met with what I'll call a "simplicity advocate," who carried the day and the complexity was tempered, if not rejected.

Anytime you rewrite 12 existing, working web apps in something new it is going to be a huge pain. The only sane way to approach this is the strangler pattern, picking one page/view in one app to rewrite, then another, hooking them up with some kind of client-side router, and slowly letting the SPA consume the old SSR pages. That way you can measure the cost/benefit of each page before deciding it should be added into the SPA.

I have had to do this approach before - I hate it so much.

Sorry, I don't have the complete context - SSR stack, app architecture, load times etc. So, I'm not in a position to comment on your SPA migration. But, I'd like to share thoughts from my current situation.

We have a flagship product written in web forms (started in 2006). It's a big solution. Performance has always been a challenge with it.

While I'm not proposing a complete rewrite into SPA, due to - migration requires a lot of effort, huge risk for missing functionality, errors etc.

The biggest problem with the product is - app posts back the entire page, which most of the times is huge, even if we changed just one field. The viewstate is enormous. My proposal is to switch to json objects for information exchange between server and client. We'll get the benefits similar to SPA without rewriting for it.

This approach is also described in MS's silk project - https://www.microsoft.com/en-us/download/details.aspx?id=272...

> My proposal is to switch to json objects for information exchange between server and client. We'll get the benefits similar to SPA without rewriting for it

If I understand your approach correctly, I often do something similar, but with modern ASP.NET Core MVC apps. Basically, I have a tiny bit of JavaScript that 'intercepts' all form POSTs and submits them using AJAX instead. Another tiny bit of JavaScript can then process the result and do something (update a table, display a message, redirect, whatever).

I feel like this gives me the best of both worlds - the backend is very testable, and really straightforward for new developers to come up to speed on, while at the same time we remove a lot of full-page renders.

You can find an example of this technique here[0]

[0] https://github.com/jbogard/ContosoUniversityDotNetCore

I recall one of the more frustrating clients at my old firm. The client was hoping to build a competitor to a fancy all-AJAX industry-specific backoffice application (written by a team of dozens and with a coffee budget alone three times our dev budget) Since they were domain experts, but sort of scatterbrained (oh, we need undisclosed requirement xyz" 3 months into development), we were building it in phases to make sure we could cover their functional needs. It was a rule-based system for validating and analyzing user-provided data, where they'd be responsible for maintaining the rules via an admin backend. It was your typical PHP based request/response lifecycle.

They. Could. Not. Get. Over. The. Fact. The. Pages. Reloaded. After. Each. Request. No matter how many times we said "can we focus on making sure the underlying math is right and then polish the UI?"

So I finally snapped and implemented that exact same thing. That shut them up enough that they just started disappearing when they were asked for info. I suspect the project had enterred the phase where they were out of money and/or realized they were trying to swallow a bigger task than they could handle themselves.

Recently, I saw Turbolinks [0] which looks like the same concept with way more panache.

[0] https://github.com/turbolinks/turbolinks

See also Stimulus [0], from Basecamp.

[0] https://stimulusjs.org/

This is exactly what the article points out. Github/Gitlab and many other projects do the same thing.

Either small parts of the application are standalone SPAs (since they can be mounted to any single root element) or there are libraries like Turbolinks/Intercooler that just make the full-page request but in JS and then replace the DOM with the results so the browser doesn't actually experience a full page reload.

I’ve occasionally thought of doing SSR but making it possible to server render only a small part of the page in response to an API request and then just use JavaScript to swap in the html from the backend.

This is elegantly implemented by [1]. I love this concept and use it in all my projects.

[1] https://intercoolerjs.org/

You could use `Accept: text/html` to indicate that an API should return html rather than Json.

You got my point right. Thanks for sharing your experience

Same issue at the previous company. Engineering team decided to turn the web app into SPA, and spent months doing this. All that time which could have been spent on building customer value were wasted.

It kept the engineers busy and for some even happy.

The hybrid approach sounds good, but I've found it frequently non-trivial to pull off in practice. In my experience, you have to be really thoughtful about what and how much you make dynamic.

For instance, if you start to rely heavily on dynamic capabilities to render key components, such as detail views/overlays, then you have to start reasoning about making them accessible via their own URL to enable direct access, browser reloads, sharing, etc. By the time you've done that, you've started duplicating browser functionality via routing, history, etc, and generally working to create an app that coexists peacefully within an app. In other words, you quickly move into SPA territory and all that that entails.

But, if that causes you to be more conservative about sprinkling in dynamic capabilities, then you're really much closer to an old school SSR app and not realizing a lot of the purorted benefits of a SPA, or much else beyond the old school AJAX approaches. Not to say that's useless, but we've long since been down that road, and it doesn't represent any new thinking.

So, it's just hard to find balance there. In most cases, you're really either a SPA or you're not.

Our team has found the balance by making a bunch of smaller, individual SPAs that make up our whole application. We follow some SPA designs, but have them more modular, and glued together by a bunch of delivery pages. We kind of get the best of both worlds, plus there's some pages and content that just render better on the server, and delivered faster through caching...

> "It drives me crazy to think that some exec came up with SPA-ing everything as a sales pitch to clients" In other companies, I wonder if this is just as often due to: (a) developers getting tired of what works reasonably well and wanting to move to a different technology and/or (b) the voices in the tech evangelist community whose own jobs seems to hinge on pitching new and shiny, latest and greatest library/framework/whatever, instilling FOMO and insecurity in the developers who listen to them about not getting on board with the latest and greatest?

On the flip side, I recently worked on a "hybrid" project that has been around for a couple years. It was a nightmare knowing when SSR stopped and SPA began. There was no consistency, multiple ways to do the same thing, and poorly maintained. It was schizophrenic.

I think the real issue you are dealing with is what others mentioned: rebuilding something from scratch burns a ton of people-hours and money. Asking a bunch of rails developers to lean into FE development is a recipe for animosity and to me it shows in this post.

The bank I used has gone from traditional to SPA style, and I wish they hadn't. There is a massive load time before I can even log in with some stupid animation, and they've reduced the exporting features. As a customer I have gained nothing. But I guess it keeps food on the table for some devs.

your anecdotal story doesn't highlight deficiencies with SPA. You only talked about the pains associated with rebuilding apps with different technology to achieve feature parity.

Yeah we have read experiences like yours again and again on every HN thread about SPA, but why we never learn? We developers kind of helping this fashion to happen.

Nine times out of ten, we developers aren't in a position to make or change business decisions of that magnitude.

Remember, every time you tell your boss to do something they don't want to do, you're telling them to spend money they don't want to spend, and if it's something you were hired to do, you're also placing your own value as an employee in question.

True but I was talking about the producer side, those cool kids in big corps. They have money backed and drive small companies to adopt the next cool things.

Not contradicting you, but how did you evaluated that the SPA is not bringing any value to the customers? It may make work harder for you, it may cost more, but maybe that cost is rightfully justified from a business perspective.

As a consumer of SPAs all across the internet, all I seem to get is a bunch of janky, slow, bloated, buggy experiences. Server-rendered views just seem more performant and reliable when done well.

Sounds like something Stubhub did recently.

Would it be accurate to characterize your opinion as "SKA not SPA?"

Agree with the article. I find server views to be substantially easier to work with.

But more importantly, I also find server view rendering to be a faster, better UI experience. It's really frustrating having to wait several seconds for a SPA to load, or to have unexpected behavior when clicking the browser back button, or failing completely because some random hunk of JS garbage errored out, and it's one of the big contributors to why I don't really like using Facebook or Twitter anymore. They murder my browser with megabytes worth of slow SPA crap to give me less than a few kilobytes of meaningful data (and/or people screaming at each other). Gmail now takes 10-20 seconds for me to load at this point, on my high end laptop. I just want to switch to HTML mode by default.

I definitely get edge cases like Slack, but honestly don't think SPA has been a positive development, overall. I think the web was better as a document/HTML oriented design.

With gmail: Move your mouse pointer down to the lower right corner of the tab. Do a forced refresh (Ctrl+f5) and you'll see some text pop up while it's loading, one of which is a link to a basic HTML version of the site. Click on it and you're back to what appears to be almost the original gmail interface. Up the top of the page you'll see an option to make it default.

It's super fast. Almost absurdly so, compared to the "full" gmail experience. Added bonus: It gets out of the damn way so you can just do what you came there to do: write and read email.

There is a direct link to access basic HTML version of GMail : http://mail.google.com/mail/h/

hm. So.

The SPA gmail platform has an _infuriatingly long_ loading screen, but once loaded the click-> to reading email _is_ quicker.

I suspect there is allot that can (and should) be done to optimize the SPA version.

But man, the html version is speedy.

I barely use email, but I'm going to put the html-only version into my rotation and see which one I gravitate toward.

That is a blast from the past. I love it.

Ahh nice, thanks!

Great example, because the basic HTML version doesn't support keyboard shortcuts, which makes it a huge step back for me.

It's certainly possible to have a server rendered app that uses JS sparingly for interactive behavior, but it blows away a lot of the benefits once you're doing significant DOM-manipulation.

If only there was a way to support keyboard shortcuts via plain old HTML...


Aren't those inconsistent across platforms? Also you must use the "super" key/combo, and there's only one. Not to mention the internationalization concerns.

Good luck implementing 10% of the keyboard shortcuts gmail uses: https://support.google.com/mail/answer/6594?co=GENIE.Platfor...

The accesskey feature is usually discouraged because it can break screen readers and other accessibility tools.

Instead of trying to quickly click the link, it's easier to just turn JS off and refresh GMail. You'll be prompted to either turn JS on or switch to Basic HTML. (You can make it the default after that, as described.)

I did this a while back, and the only real issue I've had with it is that there doesn't seem to be an equivalent to the "Check mail now" action for imported email accounts. (The 'refresh' link annoyingly does not trigger this action.)

There's a single file that's 584KB of javascript from hangouts.google.com in the "full experience" Gmail. Blocking that seems to help, a lot. I imagine there's probably some configuration to turn off hangouts that provides the same benefit.

It's in Settings.

chat off ?

There's also a hidden 'mobile webapp' version: https://mail.google.com/mail/mu/mp/167/?mui=ca#tl/Inbox

I got a popup saying the offline app is going away with a link to "setup" the new gmail app for offline use. Unfortunately the new gmail app for offline use does not support Firefox.

>Offline unavailable.

>The browser you are using is missing some features required to enable offline. To enable offline, you must use Chrome with version 61 or higher.

Thanks for the tip! I realized this existed but didn't clue in to the fact that it could be set default. I've done so now, and already feel the absurd javascript weight lifting...

I definitely get edge cases like Slack, but honestly don't think SPA has been a positive development, overall. I think the web was better as a document/HTML oriented design.

It was nice and would still be nice if browser caching meant a site still worked well over a bad connection. But you can be browsing around a "static" site and hit the back button and be stuck staring at an empty or partly rendered page waiting for your flaky connection to load the page.

SPAs handle that situation better even for sites that are theoretically not suited for SPAs. The simple principle of doing your best to display the data you've already fetched is extremely refreshing compared to supposedly "document-oriented" sites, which typically take the opposite approach -- we showed you this page fifteen seconds ago, but we can't show it to you again until we exchange a few megabytes of data with headquarters. And now we can't show you the other page, either. Just be patient. If it's really that important you should have taken a screenshot, mmmkay?

(Slow-loading web sites are the main reason my not-so-tech-savvy family members, who are very stubborn and selective about learning anything, are all adept at taking screenshots on their phones. When it comes to information they might need later, they take screenshots, because you can't just leave a page open and trust it to be there when you need it. You might accidentally trigger some navigation and then who knows how long it will take to get back to the information they need, if it's even possible.)

Browser caching should theoretically let a document-oriented web site work smoothly over a flaky connection, as long as you stick to the pages you've already viewed, right? But how often does it help even a little bit? Maybe SPAs will eventually be just as broken, but right now it seems damned cool that they make a good-faith effort to show me stuff.

You could also run server-rendering with a service worker. There's nothing about a service worker that means it only works with SPAs. It basically just gives you control over caching behaviour...

You can also control caching behavior by just setting the headers correctly in the first place. I think the takeaway here is that sometimes SPA frameworks make the behavior “just work” in more cases when the developer doesn’t put any thought into correct cache handling.

> I definitely get edge cases like Slack, but honestly don't think SPA has been a positive development, overall. I think the web was better as a document/HTML oriented design.

But even Slack is subject to the same clunky and slow user experience you're describing because its entire user interface is an SPA.

In my opinion, a site for the SPA hall of shame is the Starbucks.com progressive web app [1]. My grievances about it are legion, but to name a few:

* It's agonizing slow, both on the client and server. The server is an egregiously-slow GraphQL endpoint.

* It hasn't been tested on anything but Chrome, as far as I can tell. It flat out refuses to work in Firefox or Edge, even fresh installations I've put into VMs. These browsers may not be mainstream targets, but odds are you would have no trouble supporting them if you weren't using these unnecessarily complicated client-side frameworks for placing a coffee order.

* It routinely messes up state management. I've had it forget my selected store location; fail to add items to the shopping cart; fail to submit orders; fail to apply star points (coupons); get into a weird state where it thinks I have a coupon when the server disagrees; etc. It's constantly introducing new and imaginative ways to fail.

* If you use it for months, white-page failure modes are surprisingly common.

Every time I use it, I wish that Starbucks had made just a plain responsive web app with simple server-side rendering. It would be fast and probably work better as a way to place orders.

[1] https://app.starbucks.com/

The Starbucks app in Edge is _miles_ faster than Amazon.com or eBay.com for me on my slow satellite connection. I think this is one often underlooked feature of SPAs. SSR stuff is a blank white screen about 50% of the time for people on slow connections, SPAs have a slower initial load and then from then on are either faster or _feel_ faster because they don't go completely blank for 5+ seconds every time you click something. Even a slowly-loading SPA feels better than any SSR site for that reason, IMO.

You can do the same with hybrid approach, using service workers doesn't imply doing an SPA.

We had a very static product, and one of our devs decided to make more use of client-side rendering despite essentially being a set of unchanging forms. This quickly got out of hand, so we adopted a hybrid approach.

I built out another product, which was much more dynamic and made sense as a SPA. However, having been bitten by the forced SPA, I decided to do as much static rendering as feasible, and I think that has made things a lot easier to develop and less buggy.

Honestly, I agree that a SPA is usually a bad idea and prefer to have as much of the app be able static as possible since that simplifies things considerably. For example, slack could open a separate tab for settings (and perhaps chat history) and only have the chat parts as a SPA. It would make it slightly less fancy, but also probably much lighter on resources, faster to load, and easier to develop.

I don’t think this is about edge cases but SPA have been abused. Imagine using google docs as a server rendered experience. Or any of the apps in iCloud.com. There are use cases where it makes sense and use cases where it doesn’t.

Most of your complaints are about poor implementation but if a large percentage of people poorly implement SPA then it still looks bad. I used to say you could make a very native experience with a hybrid web app for mobile. While this is absolutely true, most people don’t pull it off so I get the critism.

Exactly. In many places slow networks are the problem, and quick spa's give a great user experience comparatively. The biggest lag in Google Docs is when it has to refresh from the server, and then it's like using windows on a 386.

I tell people don't implement SPA. Implement PWA. PWAs give you actual benefits that SSR doesn't provide (eg. offline).

I don't think PWA offline storage is anywhere reliable or predictable enough to be advertised as an actual benefit. It's essentially a fancy cache at this point:


Thank you for pointing the real issue with SPAs: they deliver awful user experience. It's quite telling how this fact is missing from the article and from most of the discussion here. We're a bunch of self-referential techies who've lost connection with reality.

I couldn't disagree more. For anyone on a slower connection (I use a satellite connection that's 1 Mbps on a good day) a SPA is almost always a greatly superior user experience. A server-side rendered application is a blank white screen for roughly 50% of the time I'm using it. Even if a SPA takes longer to initially load, it's much nicer to keep the application actually onscreen while it's loading new content. Even if the SPA takes longer to load content it will often feel as if it's faster because you're looking at the application while it loads rather than staring at a blank screen for 5-10 seconds with every click. When people talk about SSR applications being a better user experience I always assume they're operating on first-world 10+ Mbps broadband connections or cellphones in developed cities, because the difference is night and day for those of us on slower.

I also disagree with the idea that SPAs are pushed by developers who have lost touch. Clients frequently push for them and ask questions like "Twitter/Instagram/YouTube don't show these blank white pages after every click, why does my site? Can't you make it like YouTube?" Clients want to have them more than developers want to make them.

1 Mbps and each page is 5 seconds? It sounds like huge pages you are viewing

1 Mbps * 5 = 5 Mb = 625 KB

That's not huge at all, you can barely fit a few pictures into that. The page we are on require 100 KB, the page it link require 300 KB, and both aren't big and have no image to show.

I try to keep my pages down under 50k, 30k or less 80% of the time. Perhaps it's me but I think anything over 999k is insane unless it's spa or a page full of graphing function. My expectation that others are doing the same might be incorrect.

Well satellite has bad latency on top of that. Not especially large pages, I'd say. eBay, IMDb, Wikipedia.

Yep. Millions of SPAs out in the wild and none of them are good. This whole thread is such a joke. It's a bunch of posturing and no data whatsoever from actual SPAs in the wild.

> Thank you for pointing the real issue with SPAs: they deliver awful user experience.

I don't think I could disagree more with a statement, but the way I browse the internet might be different from the way you browse the internet. SPAs, when done correctly, create rich and interactive GUIs that absolutely bring browsing websites into a entirely new territory for UX. There's a reason why webapps have taken over, including desktop apps.

It's funny how Google has been banging on about "just a few milliseconds of extra loadtime and your bounce-rate increases!" while in Gmail it's like they think the product is so good, people should be willing to wait 10 seconds to view their _mail_.

The reason I'm even reading this comment section is because I wanted something to do while waiting for Gmail to load.

But the reason Gmail is so slow isn't because they've made it a SPA. It's because they made it a shitty SPA. They use nonstandard web technologies that work like ass. It was also a SPA before the new redesign and it worked pretty well.

If Gmail is taking 10 seconds to load it might be worth your time to consider a faster computer for your own sake. It can be like 3-4 seconds on a faster computer.

Nah, just tested and mail.google.com took 23.3 seconds to load in Chrome and 30.2 seconds in Firefox. I have a 4-core 8-thread i7 and am on a 20Mbps internet line. It's the website, it isn't my computer.

Is that from scratch? I'm using an i3 on a 1 Mbps satellite connection, and opening up Gmail now (having opened it earlier today), it was 0.27s until DOMContentLoaded and I could interact with it. It continued asynchronously loading stuff in the background but from my POV it loaded in 1/3 of a second, which in Chrome is faster than the app opens on my iPhone 7. I have disabled the Hangouts/Chat feature in settings which apparently makes a big difference.

Okay I can't believe that either! You're really talking about full Gmail loading in 1/3 of a second? That sounds impossible if we're loading the same Gmail...

Yeah, it's pretty crazy that there would be such a huge difference. Turning off Hangouts and using uBlock Origin might make a big difference because that's all I've really done to modify it.

Would you mind measuring how long it takes on a vanilla browser (e.g. guest mode of Chrome) without anything being turned off?

Can you try in Guest Mode (or Incognito but only if you've disabled extensions in it)? I'm guessing you either have (1) battery power or other cause of downclocking, (2) slow extensions, (3) disabled/small cache, (4) an old CPU (old gen i7 maybe?), or (5) a large distance between you and the server. I have a similar machine to yours that's 3+ GHz and it's consistently loading in less than 4 seconds when I'm on AC.

(To be clear, I'm not excusing how slow their code is, just trying to help you save some time in the long run.)

Takes 2.5 seconds with Chrome on my Quad Core i7 (laptop)

Takes 2 seconds for me on a 2018 MBP

>>Agree with the article. I find server views to be substantially easier to work with.

When working with static pages that have minimal interactivity, sure. Just render the HTML and send it to the client.

Once you get past that though, if you try to stick with SSR you'll end up with incredibly difficult-to-decipher mish-mash of if/then statements, most likely with lots of jQuery or equivalent thrown in. I've debugged such templates and they are universally messy, not just because they are usually written by backend engineers who have a minimal understanding of/appreciation for JavaScript, but also because keeping track of state with such templates is really inefficient and frustrating.

As a user, I miss pre-SPA days. For all the negatives that SPAs were supposed to solve, there was one thing about those apps, and it's that they were predictable. These days, you never know whether you can even open a link in a new tab, or bookmark it, for that matter.

SPAs are especially bad on mobile.

When browser receives HTML, either complete pages or updated fragments of them, it only needs to parse HTML, style/layout, and render. These steps are relatively fast, especially rendering (usually GPU does that).

When browser received JSON or XML instead, it needs to do all that as well (parsing is slightly simpler), but also it needs to make visual elements out of the data. Takes a lot of processing and therefore electricity: JavaScript is not particularly fast, the code size is often not insignificant i.e. takes time to download and parse the code, and the runtime is essentially single threaded (for any given page).

Facebook is not a SPA. It is SSR PHP.

You probably don't need a single-page app, right up to the point where it's a business requirement and you have to translate a GB worth of convoluted JSPs into one because the client likes smoothness in their flows, continuous saving, and all those nicely choreographed state transitions you just cannot get without having a framework hijack the History and File APIs from the browser's paws.

Yes, a nice state machine-like flow with each thing happening only once at a given time is great, right until you get asked to make it so that clicking on a thing shouldn't reset all user input, and progress of a task should be communicated live, maybe while we also we want this app to just not show a blank screen like, ever, just comes and happens to you and that's what you kind of have to do now.

This is what HN is always missing on the anti-SPA rants. It’s almost always a requirement from the client. How many hours have been wasted on here by programmers writing overwrought comments about how we’re losing touch with the user because of all of our complicated frontend frameworks? No. It’s almost always because the client’s designer wanted a real-time updating hamburger menu or whatever.

The client is rarely the user. Clients always ask for the latest buzzwords.

This is why it's important to understand the probable business requirements early.

Website != Browser app != Mobile app != Desktop app != AR/gaming platforms

If you know which of those you need, you can make an optimal technology decision. No one can expect to turn a wood-framed structure into a steel-framed structure. Nor build a steel-framed structure for the price of a wood-framed one.

In this day and age, chances are better than not for anything reasonable involved, that this smooth interaction is a business requirement, but YMMV.

not to mention the UX people coming up with neat animations and subflows with gradually revealed content.

> smoothness in their flows


> continuous saving

No problem.

> and all those nicely choreographed state transitions

Learn to say "no." It works wonders whenever people tell you that your aircraft has to go under water now.

It's difficult to tell the person who's writing your paycheck "this is totally possible I just don't like it and so won't do it."

Like if you're doing SSR you could at least use something like turbooinks to implement state transitions.

How about “that’s totally possible. It will cost you 10x what you’re paying now, it will be much more brittle and harder to fix. I personally would love to work on it, just keep in mind that any changes will require 10x the time and budget”

And ...

“Here are a couple of technologies which would allow us to speed up the experience at a very low cost. I recommend we try these first.”

Turbolinks for the win :)

> It will cost you 10x what you’re paying now, it will be much more brittle and harder to fix.

I say this as someone who's done a lot of freelance work: No, you can't bullshit your clients like this. You may be able to tell them that if it's not an actual lie, but in your case, if you actually would endure such costs and fragility, it speaks volumes about your agency's skill levels.

If you're in the business of selling websites, maybe it's time to actually learn how to write a good SPA rather than bury your head in the sand, because yeah, clients do actually want those.

Maybe I should’ve made it clear that the 10x is an example. In most cases it would be 2x to 4x, the cost for implementing two apps instead of one.

Of course the cheaper option (monolith app + turbolinks and js sprinkles) could be framed as a discount.

And I can imagine how many agencies would not mention the expense of maintenance, because they’d actually want to lock in the client first.

10x the cost!? Well, I have a quote from your competitor that's a fraction of that amount. If you keep quoting unreasonable prices, perhaps I should rethink our business relationship and move elsewhere.

Sure, you can say that. You will lose your clients to the agency down the road who happily use React and say "no problem." Especially once it turns out that it _doesn't_ require 10x the time and budget and your prospective client tells everyone you bullshitted them.

...and it breaks linking to URLs and backspace.

Turbolinks? Huh? You have to write your code keeping turbolinks in mind because certain onload events will only fire once but you use turbolinks specifically because you want those things to work but want the speed advantage of not doing a full page refresh.

> learn to say no

Good luck keeping that client after the end of your contract.

All that complaining serves no purpose. SPA is just another tool in a belt. Where I think it shines is making rich apps that need complex flow and communication. This is where productivity is important and the process is complex and up until recently I would be advocating native desktop app. Now with advent frameworks that help me organize this very efficiently (I use re-frame/reagent with ClojureScript) I can create complex SPAs without the project collapsing under its own weight at some point.

I don't want to say you should use SPA frameworks for anything, don't make your company website with SPA. What I want to say that if you have a complex process you can consider creating "enterprise" UI instead of trying to dumb it down to a series of billion simple forms.

If you feel your business is overusing SPAs (is it so strange they want new shiny toy?) then as the technical person you need to educate them on pros/cons of the technology.

> All that complaining serves no purpose.

It's not complaining. It's a profession's view on the state of (default) behaviour by most developers in the wild. It's a valid set of points as to what the default mode of operation seems to be, as a general rule, and why it might not always be the correct default mode of operation.

> I use re-frame/reagent with ClojureScript

I personally feel like what's really missing here is something like a generic spec (not a generator, but a descriptive standard) for the structure and organization of CRUD-style JS/JS-derivative SPAs, something like what re-ducks (https://github.com/alexnm/re-ducks) did for the Redux world.

The complaint is that it's a tool that used much more often than is necessary or even advantageous. Just like that old saying about hammer and nails.

Unpopular opinion: I love SPAs for simple stuff. Yes, they're a ton of work. But the feel of them is unparalleled.

I have my personal home page written as a Vue SPA. It was a silly amount of work to get together, and not everything works perfectly. BUT: it moves like a rocket. I pre-render the simple front page, so initial load is nearly instantaneous (especially with cloudflare &c), and, by the time a visitor finishes absorbing the information on the front page (which is just a palmos style collection of icons to other content), everything else is loaded. Which means that the effective load time of the whole website is perceptually indistinguishable from zero on a moderate-speed connection (like my crappy home DSL).

And that's... cool. It's legitimately cool. Let me have my fun!

I want to be open-minded for you to have your fun. But at the same time, I want to let you know the problems with your approach from my perspective if you want me to interact with your site.

No offense, but I don't know you, so I'm not going to run untrusted code you serve my computer without some good reason. That means your website is completely broken for me. It is also likely broken from an accessibility standpoint for those with special needs or using tools to access your webpage. (edit: People's personal browser defaults such as size, font, scrolling, language translation, or any other plugins they use for their workflow may easily break.) It also means that search engines and robots will have a hard problem indexing the links on your page or understanding the layout of your site.

So while I could agree you've created this cool user experience for the most common case, it breaks the fundamental precepts underlying the web and I think this does have some negative consequences, especially if this became the default approach. That all said, you do your thing - I just hope this provides useful food for thought!

Relying on JavaScript doesn't "break the fundamental precepts underlying the web", that horse has sailed long past that bridge.

Today, not running JS breaks the web. You can lament this, I too think it's not ideal, but you can't change it. So don't accuse devs of breaking the web for using an SPA just because you're part of the 0.002% of users that doesn't run js by default.

Furthermore SPAs do not break accessibility, that is nonsense. Devs may break accessibility if they choose to reimplement components without thinking about it but that has zero to do with SPAs.

Hi and thanks for your responses. I think you may not be considering my post in the context of the above person's webpage. I would be interested to hear if you see my perspective a bit more after viewing the page and its source code if you haven't already.

(1) I do think I can make a small difference toward making the web better by pointing out the drawbacks of unnecessary JS. I also think it's fair to describe this page as breaking the way hyperlinks usually work on the web.

(2) I don't mean to say all SPAs always break accessibility -- again this is all in the context of the page above. I do think, for the reasons I gave, it's fair to say that a plain HTML page with a list of links is much more amenable to generic accessibility tools than a block of JS that emulates behavior of links.

I misunderstood your post regarding accessibility then :) it's unfortunate but some react and Vue patterns tend to lead to a lot of div soup. It doesn't have much to do with the tooling but rather a lack of education for the devs on the subject and it's a testament to how easy it is to create custom components in both.

> I also think it's fair to describe this page as breaking the way hyperlinks usually work on the web.

Well maybe. A good SPA imo will render the first pageload with SSR, which means that your links will actually work the same. You share a link or open it in a new tab or whatever and it will load a page full of HTML that might not even need JavaScript.

SPAs do hijack the link system but they do so to retain natural back button functionality. Back when they didn't, people complained about that, rightfully so.

Howe there's nothing emulating anything. SPA links are anchors, as they are anywhere else on the web, and all the apis are native to the browser. It doesn't have anything to do with accessibility, no.

The more you write SPAs, the easier it is to set up the next one... This whole "but SPAs are bad!" tirade a lot of people have been going on since a couple years ago stinks of people being nervous about their job security.

https://martinfowler.com/bliki/MonolithFirst.html -- you're right, Martin Fowler, that guy no one has heard of, is just nervous his job is on the line.


It's a perfectly valid point to make: splitting everything up into SPAs, micro services, etc, instead of solving the business problem with a monolith is indeed the wrong way to go, and Martin makes some sensible arguments around this topic.

It's the same in video games: you create a prototype using cubes and texture-less blobs to test the "business logic" (mechanics) first before you produce a AAA model and 700 animations.

The site is very simple (6 icons links on the homepage and just plain text on the subpages) this could have been done as a static site quicker with even faster rendering. As a bonus you may get external traffic to your cv page if it was separate.

I do like the big icons on the homepage and I'll just say great job.

You used an spa because it was easier for you and that makes sense. One npm call and oje starter kit can get you a finished emtpy app. Doing it in plain html should be even easier but we lack the all-in-one modern tool it seems.

Well said. I think combining SSR and SPA by making intelligent tradeoffs is the way to go at this point. It's all about making the right choices to deliver the experience you're trying to offer.

Fun is fine, however, it can distract from the task in hand. Accessibility is queen.

No criticisms here, just observations on what gets missed generally by people who go too far along the build tools path and overlook things like document structure along the way.

The actual document could benefit from HTML5 niceties such as more accessible elements than 'div' and the table elements. Table has its place but the world is moving on to CSS Grid for proper layout of content rather than tables. I prefer to see 'article', 'section' 'aside', 'nav' and even things like 'cite'. For added usefulness to Google a few structured markup snippets for all of your publications will help nicely. The schema.org 'article' is a good place to start on that, you can also render your HTML from this structured data if in JSON+LD if you insist on clever wizardry or just put the Rdfa (or whatever) tags in the HTML.

The UX is not truly accessible, the home button is not a good touch target size plus the navigation is against the 'don't make me think' principle.

So it might 'move like a rocket' but if the site visitor can't work out how to get the navigation then what is the point? A vast magnitude of time is lost.

A favicon could help with accessibility too. If someone has lots open then a tab identifier helps. Go through the necessary to make a PWA instead of a SPA to get that right - nowadays you need lots of different things for 'add to homescreen' and whatnot. Whilst you are at it include some useful metadata in the header for people sharing your page on social media. Set the meta description with 'nosnippet' so Google shows people exactly what you want them to see. Nobody sees your site before Google so it is important.

Sometimes a focus on gadgets is counterintuitive, so the inline SVGs base64 encoded might be very clever, but to someone that understands SVGs this makes no sense at all. They are better as document content, not in an img tag and not base64 encoded. They will compress better that way too.

If you did the SVGs normally then you can use currentColor to effect a mouseover, you can use their title tags to show some text on the mouseover.

Also, writing an SVG as something like this:

path d="M384 1408q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm0-512q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5h-1216q-13 0-22.5-9.5t-9.5-22.5v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5zm-1408-928q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5h-1216q-13 0-22.5-9.5t-9.5-22.5v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5zm0-512v192q0 13-9.5 22.5t-22.5 9.5h-1216q-13 0-22.5-9.5t-9.5-22.5v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5z"

is a bit bulky when what you really need for that is to do (pseudo svg here) 'group fill=currentColor stroke=none id=circle-and-line' [ 'circle r=[radius]' 'rect x=[origin] y=[origin] width=[width] height=[height]' ] 'use y=[minus-a-bit] href=circle-and-line' 'use y=[plus-a-bit] href=circle-and-line'

In that way you can get a super concise and super editable icon for your CV that you can edit and tweak in document. It will also have the currentColor niceties. Sometimes I think that just because you can put sausages in a blender doesn't mean you should. Those SVGs really are wrongful being inlined and base64 encoded when HTML provides perfect and better mechanisms built in for doing whatever it is you are trying to achieve with them. Also, SVGs are best hand drawn for a pet project site, internet SVGs are just the disgorgings of an Adobe product, normally shapes for icons can be drawn with rectangles, circles, polygons and lines specified with integers, the Adobe products use NASA numbers instead (none decimal places).

I would say that you would have a lot more fun if you got the basics of document structure, accessibility and awesome SVG goodness done right, with measurables in Google search results and eyeballs.

We all live in glass houses and I am definitely throwing stones here with this critique, but the web gets better with a little bit of discussion on these things.

I certainly think most of this stuff is right. I've been meaning to go through and make the whole thing more semantic, just haven't gotten around to it yet. So I really appreciate your thoughts, most of that stuff is going on the todo list. (Maybe not the SVG stuff; the way I do the SVGs is a lot more convenient for design flexibility.)

(But, to the original point, all of those great suggestions are totally compatible with doing things SPA-style. And actually, Vue components are so composable that these kinds of changes should be pretty easy when I get around to them.)

You have some neat SVG icons already, I urge you to refactor them so they are not 'design assets' but fully fledged and fully yours. The exercise of doing them will give you a new string to your bow for solving visual problems. SVGs are like LEGO but a lot more fun, so long as you play with them properly rather than just use ready mades. So same as LEGO then...

Once you have done a small set, e.g. your dozen ones, you will be able to have more of this design flexibility, plus you will discover that creative drawing is not actually what usually goes on with Adobe style applications but goes up to a whole new level when you do SVG - because it is code.

If embedding SVGs has cool factor, you can make them fully presentational by putting them in CSS custom variables and then using those custom variables in pseudo elements. This is how I do external links, download links etc.

The only downside is that you can't radically change the colours on mouseover etc.


Also Google Lea Verou if you want to take pride in your SVGs.

To add to your refactoring list, have one stylesheet with everything that changes depending on screen size set as a CSS variable. So at the top have a big list of 'things that change' and the defaults for any screen size. So if you have margin size for instance, set it there for mobile, then, have a media query below the base list of css variables and then update the variable in the media query block. Try to have zero CSS rules in the media queries, have it exclusively setting CSS variables.

If you do it this way then you can tell from the CSS where something changes because it has a CSS variable. Done the old way with chunks of CSS in media queries you can't see at a glance if there is more than one place a given rule is defined, done the new way it can be maintained a lot easier.

A final thing - you have a lot of table information and CSS grid is absolutely excellent for showing tables. You don't have to explicitly write out all cells, unlike with tables, you can make things with a given class or other attribute go in the correct column keeping your source data semantically neat even if some records do not contain all the fields. Rather than classes you could mark up your 'papers' and references with things like 'cite' tags, 'address' tags or whatever is bestest HTML5 and have these flow into the correct columns without using classes or tables, just a succinct css grid declaration and that is it. The grid layout is much better for speed so you will like it.

That's clever. Could you give me some pointers on how you made (just) the front page pre-render, while the rest of the app loads?

I'm more interested in the future of "you probably don't need a native app".

It feels like browsers are closing the gap pretty well with things like IndexedDB, offline features, WASM, etc. Still a ways off, but seems like it's getting there.

I do worry, though, that it's not really in Apple's or Google's best interest to move that along.

It's in Googles interest as everything they deliver is through the browser. Not so much for Apple or Microsoft though. Personally I will be quite sad if I end up loosing so much control over my computing environment.

Native apps allow Google to collect much more information than they can via the browser. They also allow for a wider range of advertising opportunities.

Except for people who won't put up with advertising in native apps.

Adblocking on phones requires infinitely more hoops to jump through than using a browser adblocker does.

Google's services are incredibly convenient and well made, and you may be assuming people will give up those conveniences. That's a big assumption and I think it wont pan out that way.

Based on the number of Windows 10 users, that's a very small percentage of users indeed.

They don't need to show you ads in their apps. They just use them to collect your data, like where you are every moment of every day and use that data to better target ads.

Android and Google Search are completely different Google departments. They will fight for the audience as long as they won't directly compete with each other. Board can see this as a widening audience, cementing presence and reaching new markets. It's in the best interest of Google Search and Chrome to push browser apps ahead.

Apple makes more than $10 billion per year on advertising just from one deal with Google alone. Microsoft has $7 billion advertising revenue.

Well it would cut into revenue from the PlayStore. I suppose it's plausible that keeping people in the browser is a good enough trade-off for Google.

I can’t imagine that the Google Play Store is a huge revenue generator, relatively speaking of course.

That’s much higher than I’d have expected. I wonder how much of it comes from games and their in app purchases, a segment that is unlikely to take much of a hit from moving other apps to the web.

As browsers close the gap they simply become the OS but slower, more abstracted, and with less security. And they stop being good browsers. It's the old emacs situation come round again.

The only positives are to corporations and institutions with profit motives to decrease dev time and increase ability to spy on users and extract rent from them.

> they simply become the OS but slower, more abstracted, and with less security.

I agree with slower, at least for computational tasks, but not security. Do you feel safer installing an organisation's native app than using their web app?

> The only positives are to corporations and institutions with profit motives...

What advantage does the web give to corporations that native apps don't? You mention spying, but the native mobile app ecosystem is filled with tracking and analytics code (and it's easier to hide it). The only corporation-level difference I can see is that native apps are heavily tied to a specific company's platform, while web apps aren't. This is a huge positive to the web - I've felt free to change platforms many times.

A second huge and underestimated positive of the web is backwards compatibility (ie. lower maintenance headaches). A complicated internal web app I wrote eight years ago is still running despite not being modified. The websites and lousy javascript I wrote as a kid in 1999 still run exactly the same as in 1999. Spacejam.com is unmodified from 1996. Yet I have many native apps from two years ago that no longer run correctly due to OS updates (especially on mobile).

> As browsers close the gap they simply become the OS but slower, more abstracted, and with less security

Browsers are forced to implement standards like CORS, single-origin policy, and multiple levels of SSL certificate validation and thus are more secure than most of native apps. How do you know whether that mobile app is not signing in over HTTP? In a web browser it's obvious instantly.

> motives to decrease dev time and increase ability to spy on users and extract rent from them.

Literally the worse what can happen over web browser is tracking based on various forms of fingerprinting. Native apps? MAC addresses, SSIDs, serial numbers - EVERYTHING is available for the native app to send ANYWEHERE, even over HTTP.

> and with less security.

v8 is probably one of the most strenuously vetted pieces of software on the planet.

This is the only reason we have an SPA to begin with-- small team writes a single frontend and deploy to web, iOS and Android via Cordova, Windows via Electron, and (previous) Chrome OS via the now deprecated Chrome App APIs. If we didn't need to support the full experience on all these devices, SPA would be way overkill.

Native will always be the best solution... Because it's native.

Technically best doesn't always win the market. I'd love not writing 3 versions of every piece of functionality.

How's that working out when there's more than one browser you have to account for? What's the difference between polyfill or some framework, and something like Qt or SDL?

Or I suppose we could just all use chromium, but we could also just all use Windows.

> What's the difference between polyfill or some framework, and something like Qt or SDL?

As a user, I usually can't even tell when they're using a polyfill on the web (except when they stop, like GitHub did with type=date). (As a developer, I often can't tell the difference, either. Some of them are that good!) So long as you generate HTML/CSS/JS, it doesn't matter to me how you do it. That's as 'native' to the web as you can get.

I can spot Qt a mile away. A lot of the visuals look wrong and a lot of the controls don't behave right. It's frustrating to use, and I always slow way down and double-check my work because, e.g., popup menus show the 'accept' animation even when you cancel them.

> I can spot Qt a mile away. A lot of the visuals look wrong and a lot of the controls don't behave right.

You mean it has no respect for your native toolkit... just like the web?

"just like the web"

How true is that? I was under the impression that for Android and iOS, Chrome used the native widgets for most things.

How many SPAs use native controls with minimal styling?

I have to write it for the web already. Writing a native Android and a native iOS app is additive if the web version is "good enough".

There's no scenario where I only have to write two native apps. Perhaps there is for other people.

Consider that maybe there are uses for software where the web isn't necessary and isn't even the first choice.

You're a hammer, so everything is a nail. The reality is that the web is a horrible choice for a whole lot of things. It's a document platform with parts of an application platform shoe-horned in and bolted on, and the result looks like a garbage fire to people who come from the land of native software.

I'm not sure I understand why browsers getting closer to native apps ruins anything for anyone else. You're still able to hammer your nails however you want.

I'm sure it's nice for you, but users like me aren't happy that every mouse move and page load is cataloged and studied and shared with partners. At least with a native app I can add a firewall rule to restrict it's ability to use the internet.

Users like you represent a tiny, tiny minority. The majority of people couldn't care less about google tracking their mouse movements.

The majority of people are not aware that someone is tracking their mouse movements.

I'm guessing you don't live in the EU.

You're just externalising the time you save as a cost to your users.

It's equally possible you're doing the same thing by forcing users to download a native app. It's kind of hard to talk about in the abstract. Some things work better in an app, for other things it adds nothing notable.

> not writing 3 versions of every piece of functionality.

React Native and ReactJS are a move in the right direction.

I wonder if we'll get React NativeJS

Not sure exactly what you mean by React NativeJS but perhaps React Native for Web (https://github.com/necolas/react-native-web) is along the lines of what you are thinking?

Works remarkably well. It’s already used for Twitter’s mobile site

Have you tried Angular+NativeScript? one piece for all (minus UWP).

wxWidgets would help with that.

Except when all your content comes through the pipe, in which case native is just a glorified iframe.

Native has downsides too, like having almost zero control over the client and being unable to link other people like you can on the web. Just a bunch of silos by design.

Native is only a trade-off that has great performance at other expenses.

Not always. There are times when you don’t want to download an app for every little thing, though the opportunity to be able to do so is nice. There’s a reason we have browsers and not just everything coming through in its own individual app.

Web is best because it is platform independent.

Resource consumption will be worse, doubly so when they make an app out of the SPA via electron&co.

I look forward to a similar article saying "You probably don't need WebAssembly."

I mean, it's neat and all, but most websites aren't CPU-bound.

I didn't view WASM on its own as the big differentiator. But, it is one of many things that's closing the gap between native apps and web apps. As you mention, it's useful in some situations.

Having developed with nodejs since v0.4, went through jquery => backbone => angular (1) => ember => vue => react, written stuff in several incarnations of javascript (including coffee and typescript), used build tooling from grunt to webpack and customized browserify, even built stuff with meteor... i can‘t bear it any longer.

Actually now we are full circle again. Files that mix css/template/logic with FOTM syntax, add some database calls during SSR and you have basically PHP. Just more complicated tooling. Deploy your frontend on S3 and its similar to FTP to Apache Servers, except you can‘t update just individual files. Run your backend on AWS lambda and you have stateless backends like ... PHP, but with cloud vendor lock-in. State Management like „Flux“ that poorly resembles state machines on top of JS shortcomings.

I am personally switching completely to elixir/phoenix to do anything web-related and can solve things cleanly within minutes. Also when Phoenix LiveView finally arrives, it could be groundbreaking and replace many usecases of modern SPAs.

I used to feel that way, then I met a one javascript developer in particular who really made me see it differently. I won't get into those here, I just want to tone down the "probably don't need" into a "don't necessarily need".

As a predominant back end developer, I do feel that the complaints from the article are due to inexperience or misunderstanding:

1. stateless requests: You don't have to cache any state by default, just like server side. You start caching to improve performance and caching is always one of the big 2 problems of computer science. Don't cache if you don't have to: stateless has benefits.

2. Reinvent browser features: use your framework! This is a solved problem. I am not sure what the Angular or React solutions are but with vue just use the vue router.

3. More mature tools: backend suffers from this as well, I know a lot of mid level software engineers that are always chasing the latest fads. Microservices, containers, serverless, etc. The biggest issue I had when I tried to do serious frontend development is just not being aware of the tooling and how it works.

4. SEO: Google can crawl your webapp: https://searchengineland.com/tested-googlebot-crawls-javascr..., I would prefer if the person making the claim (that an SPA does not get crawled) would be the one providing the evidence...

Don't get me wrong though. Sometimes an SPA is the wrong choice but it would be hard for me to say if that is usually, rarely or a toss up.

I think many places that go from server-side rendered to client-side rendered SPAs do not hire a bunch of front end experts when they do so. Then people experience a bunch of problems because of the fact I point out in 3: lack of awareness of the ecosystem. On the other hand, there sure are a lot of diva developers who don't like working with old technology (for example, PHP), and this probably causes a lot of the front end framework churn. Just like picking up a new language, it takes time to produce idiomatic code. Of course, for a new framework it takes time for the idioms to develop...

Google isn't the only search engine. But even if that is the only one you care about, Google said themselves in last years IO conference that it takes them several more days to index a client rendered interface, since they have to send it to a rendering queue, and the line is really long.

Here is the talk: https://www.youtube.com/watch?v=PFwUbgvpdaQ

> I am not sure what the Angular or React solutions are but with vue just use the vue router.

For React there's a couple, but most of them boil down to the same basic idea that you've got switch statements that decide which components to render based on router state (rather than there being anything "special" about routing entry points), and then something like a <Link> component that just acts like an <a> tag but triggers the client routing change instead.

I used react-router before but absolutely hated how it mixes presentational logic with URL matching. For new projects I just use a small routing helper that’s written using React context and that performs URL matching the old fashioned way (a list of pattern with parameters that are routed to specific components). Works really well on all modern browsers and is less than 200 lines of code. It even allows for reverse routing (use a view name and parameters to generate a URL) which to my knowledge isn’t implemented in react-router.

> I used react-router before but absolutely hated how it mixes presentational logic with URL matching.

You may like redux-first-router, which has the URL literals as part of a routemap attached to the Redux store, and then has all routing in the app actually just be the dispatching of Redux actions. Your navigational components then end up with stuff like:

     <Link to={{ type: THAT_PAGE_WITH_THE_STUFF }}>Link text here</Link>
...where the Link is actually just a convenience helper component wrapping <a> that dispatches the action and provides a browser-friendly href reverse-engineered from the routemap if possible.

Regarding 3: The Browser does a bit more than routing and no framework (as far as I know) handles these simple cases by default:

- Timeout error / no network connection

- Ability to stop requests

- Show that the browser is sending a request

Those are excellent points to consider.

Also, in the favor of SPA's you can consider the horrible state of repeating post requests when users press the back button on server rendered multi-stage forms (like purchasing a flight ticket). Of course, you can just avoid implementing multi-stage forms via POSTs like this and I wish airlines would stop.

If you implement your SPA with a service worker and use cacheable GET's properly, your SPA can work offline and survive temporary network glitches (like on a train) in a way that server rendered apps never can.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact