
Escaping the SPA rabbit hole with modern Rails - mparramon
https://medium.com/@jmanrubia/escaping-the-spa-rabbit-hole-with-turbolinks-903f942bf52c
======
peteforde
I have nothing against SPAs for complex UI interactions. It's sort of like
taking anti-biotics; there should be a moment of reflection when you should
justify your true need, lest the cure be worse than the disease. Most
developers of a certain age have come up when it's SPA by default, and can't
truly defend why they need it.

In this thread, there are several claims that it's impossible to write well-
organized jQuery. That sounds an awful lot like dogma to me. Also, your
inability to write well-organized code says more about your coding and team-
management skills than it does about any one approach. Any tech is only as
good as the team using it.

A few years ago, Sam Stephenson (who originally wrote the Prototype library,
before jQuery was a thing) gave an excellent talk on Turbolinks at RailsConf.
I recommend the whole talk (turn it up to 1.5x speed, of course) but at 4:12
he does an amazing job of showing how the SPA path leads to insanity.

[https://www.youtube.com/watch?v=SWEts0rlezA](https://www.youtube.com/watch?v=SWEts0rlezA)

Here's a mental exercise for you: the next time you start a new project,
instead of deciding which SPA framework to use, start with an assumption that
an SPA is wild overkill for the first iteration of your application -
especially if few people on your team have working expertise with the SPA in
question. Then see if you can argue FOR the tech. It's much harder to justify
something you don't need if you start with an honest conversation about how
you probably don't need it. (This works for throwing out CDs, too: start with
the assumption that they are all garbage, they all go. Then force yourself to
make logic-based arguments for each one you keep. Your outcome will be night
and day from if you start with everything in a keep pile.)

~~~
cm2187
As a user my main beef against SPA is that most of the time they break basic
browser functionalities, like the ability to open links in a new tab, or using
the back button. When the UI doesn’t simply break with part of the content
off-screen.

~~~
thesephist
Having built some SPA's, I'd argue that at least those two things that you
mentioned are the fault of whoever built bad SPA's, rather than issues with
SPA's as a whole. It's possible to build an SPA that works well with the
browser controls because modern browsers expose a lot of their functionality
to JavaScript (like it or not). You can use <a> tags for buttons and links in
an SPA (and keep the link functionality) -- you can just intercept the clicks
when the link is being opened in the current tab, and you can always hook onto
pushState/popState to make the back/forward button work.

~~~
temporaryacc62
Would you say Youtube works better now as it is fully SPA?

~~~
fny
There's an army working on YouTube, and it has the traffic levels to justify
the investment. They can actually put in the required effort to ensure the
application functions seamlessly and meets accessability standards.

------
wjossey
To the author of the article- Kudos! Well written, well reasoned, with minimal
hyperbole or unnecessary “X is dead” style declarations. Hope we see more
writing like this bubble up to the top on HN.

I’m not swayed by the argument, but that’s personal bias. I’m the technical
cofounder / solo coder of a venture backed startup, and I built our platform
on rails 5. I migrated our front end to Vue over the winter and couldn’t be
happier.

When we started (my cofounder and I) our company in early 2017, it had been a
few years since I coded daily, and I’ve never been a front end programmer. I’m
not well skilled in JS, so I punted on using any front end frameworks for the
first six months. Our entire MVP was rails 5 server side rendered pages, with
a dusting of jQuery when needed. It definitely got me as far as I needed it
to, but I felt a lot of pain once I began to try to mix in a lot more
interactivity in the app. For me, migrating to Vue made a lot of sense and
continues to pay dividends. For others, the author’s arguments are probably
far more applicable.

One area where I deeply agree with the author is around how in JS I often
don’t know exactly where I should write certain parts of my code. For a long
time, I had a lot of model logic in my Vue components, but that quickly became
a nightmare and I’ve abandoned that. Now I use ES6 classes to wrap a bunch of
my logic, but even then I still find stuff bleeding places that seem wrong.

One thing I also avoided so far was using any state management (a la Vuex). In
some rare examples I use a message bus to send information around, but even
then that usually triggers a component to go refetch information from the
source of truth (the API endpoint). So far this pattern helps to restrict me
from making certain lazy choices which will feel good in the moment but become
maddening in the future. My app, as such, is not as maximally performant as it
could be, but the trade off for the rare update has so far felt worth it.

So, to sum it up, as a veteran coder who spends 12 hours a day writing code,
but knew rails really well and not any SPA frameworks, I’m sympathetic to the
article but respectfully have a different experience.

~~~
sho
> I felt a lot of pain once I began to try to mix in a lot more interactivity
> in the app

I don't think you're actually disagreeing at all. You're using the right tool
for the job. You started with one job and the right tool, and when the job
changed you switched tools. That's as it should be!

Use Rails until you can't. That's what you did and I can't see the author
disagreeing.

You can generalise this to most technology. I know someone who has gotten it
into his head that he needs to write his entire new web app using golang and
microservices. I'd suggest that when he actually outgrows Rails enough to
require that then he can suggest it to his 50-person-plus engineering team,
but in truth I don't think he'll ever actually finish it.

~~~
debaserab2
Another plus to this "ramping up" of tools as necessary is when you get to a
certain point where your entire UI is sophisticated enough you can cut the
views out of your rails app and basically transform it just a REST API with
another service responsible for serving the UI layer.

Rails makes a fantastic REST framework, especially if you build your app that
way right from the start.

~~~
wjossey
Good point, and this is exactly what I did. I actually was running the SPA +
the rails app side by side. Took me about 6 months, but I cut over every page
/ app one by one till I was done.

And, to the parent commenter, good point. I do think the gist of the author is
to use the right tool for the job, and they are not dogmatic about "never
write an SPA". Thanks for keeping me honest.

~~~
andrei_says_
I’m curious, what was the change in the UI which required the move away from
Rails?

What are you accomplishing with Vue which was impossible before?

Would love to get a glimpse of the app.

~~~
debaserab2
I'm not the OP, but here's how my Rails app is growing after several years:

The first "complex" UI design that we came up with was creating a list view
that came with all the trinkets you'd want from a sophisticated list view
(pagination, sorting, filters, searching). This view needed to be able to
apply easily to all the key data structures our app uses (list of users, list
of things user has, list of things users do, etc) which meant due to the scale
of some of the data sets most of the operation work needed to be on the
backend.

Originally, it was built as a completely normal Rails view requiring a full
page refresh (form submit) to perform any given operation. This certainly was
"doable" but not a great experience as someone administrating lists of things
in our app.

We then wrote a React component that manages all the visual state itself based
on the data returned from the backend and replaced the existing Rails view
with this React component. By pushing responsibility of view state to the
client our Rails codebase get simplified. React fully manages visual state,
but where we really benefit is the fact that it forces you to design
components in such a simple way that UI abstractions become more naturally
fitting. The conventions are easy to understand and result in a codebase that
can have a lot of cooks in the kitchen without too many problems.

Could this be written in jQuery? Sure. If it's like most large jQuery projects
I've seen with multiple hands on it, it will be hard to keep it from being too
brittle.

The implementation is really part of a longer term plan to begin building out
new user interfaces in React. We find that react delivers on the promise of UI
reusability much better than any backend MVC frameworks view or partial
system. A front-end codebase is starting to emerge with it's own developer
conventions and processes that are more geared towards frontend requirements.
Meanwhile, our backend is simplified to only deal with tasks related directly
to data management. The split feels very natural as the codebase grows larger.
There is no obvious downside to writing in React besides the minified library
code payload.

As a summary: our users expect interactions with complex interfaces to respond
quickly. React is designed to build interfaces that fulfill that expectation,
and the implementation of React in our codebase allows to slide into a more
microservices looking architecture in an organic way as the scale and
complexity of our app increases.

------
lucidone
Are you building a website? The practices espoused by the author will be
ideal.

Are you building a web app? Will you have a mobile client alongside your web
app? Using a javascript framework for your client(s) and decoupling your data
from it's presentation will be a fruitful investment. All of these frameworks
and their associated happened for reasons, and they didn't involve traditional
MVC being good enough for everything.

As an aside, I find this viewpoint prevalent in the Rails community and the
Rails job I had (so, caveat, I'm coloured by my personal experience). It also
lead to a culture of staunch refusal to learn or do anything new in that job,
and the quality of the product suffered. It consequently led to me leaving the
job, and being much happier for it.

~~~
zmmmmm
> It also lead to a culture of staunch refusal to learn or do anything new in
> that job

I find one of the most difficult aspects of software is the very powerful
"local minima" of effective (but not optimal) techniques combined with
entrenched knowledge. People are so incredibly biased towards what they know
well, and that bias is backed by objective evidence: when they do it X-way
they are objectively faster AND better, and what's more, X-way has many
objective benefits. This is the local minima in a vast multidimensional space
of the benefits and tradeoffs of different possible technical approaches. The
multidimensional problem of overall comparing X-way with Y-way is nearly
impossible to accomplish, so we nearly always fall back to our intuition (aka
bias) which nearly always leads us back to what we already know. And
consequently most organisations are stuck in some version of a local minima
that is very hard to escape, but ultimately represents a big disadvantage over
time. But the question of when is the right time to move out of that minima -
and incur the expense of navigating the hills between where you are now and
the better minima - is really hard to solve.

~~~
sho
I totally agree, but I thought it was funny that you invoked the concept of
local _minima_ \- I have only ever heard that concept in terms of local
_maxima_ , ie locally-but-perhaps-not-globally maximal productivity, comfort
zone, etc. I assume you are referring to a locally/globally minimal
resistance, time taken, or some such?

Anyway I just thought it interesting that you might make valid reference to a
very useful concept I've heard and used many times, and yet in your expression
the "polarity", as such, is totally inverted! And yet I understood you anyway.
A computer would be totally confused.

~~~
adrianN
Local minima come from optimization problems as you encounter for example in
Machine Learning. You usually want to minimize some error function (e.g.
misclassified objects). Unless you take great care these functions are riddled
with local minima where naive optimization gets stuck.

~~~
sho
Ah I see - of course. Should have thought of that.

For comparison, I believe my usage arises from evolutionary fitness, where one
might discuss local maxima on a fitness landscape. The challenge is perhaps
much the same as in ML, with one strategy being to introduce random mutations
in order to escape the same kind of trap.

------
zmmmmm
I have to admit, I do not know Turbolinks well, but I feel like the author
misses something fundamental about the benefits of modern frameworks. It's not
just about building a giant SPA - component-based design is a huge value
proposition.

The problem I see at the moment is that client side "apps" \- however they are
rendered - hit a wall in complexity that is really hard to overcome without a
a sane and sensible way to break them down into pieces. Just like every sane
regular programming language has concepts of classes or modules or some kind
of system for divide-and-conquering problems into pieces, your front end needs
that too once it gets complex. And that's what these React/VueJS frameworks
are doing for me. What I like is that they make the _right_ solution -
breaking a piece of logic or code into its own component - the _easiest_
solution. So I tend to _do the right thing_ , not because it's "the right
thing" but because it happens to be the _easiest thing to do_.

I know this is a bit of a parallel argument with respect to whether you build
a SPA or not (especially Vue can live in either world just fine). But I feel
like the author is throwing out the component-baby with the SPA bathwater.

~~~
simplecomplex
Components aren’t a well defined thing. Most people mean “React class” when
they say component. React apps are much more than components. Some components
have their own state, some don’t, some touch global state, routing and data
fetching are often not components.

“Component” web apps are by no means simple.

------
schizoidboy
> For your SPA logic, you will want a rich model of objects that represent
> your domain and its rules. And you still need the same for your server
> logic. And this recipe is just a duplication waiting to happen.

Great article overall but one premise I question is: how often do you really
need a non-jQuery JS framework at all in the client?

It seems to me that most apps are simple CRUD apps and server-side rendering
is sufficient. Sprinkle in jQuery for simple client functions. Use
jQueryMobile for the SPA framework which improves performance by making an
AJAX request for any navigation and replacing the page body (instead of doing
a full page reload).

I recommend only moving to a full non-jQuery based framework if the design or
functions require it (and question that) or the app evolves to require it. As
fast as computers, phones, and the internet are today, doing server-side
rendering seems good enough for most apps.

~~~
woah
In jquery programming there’s a huge difference between how the stuff that
shows up when loaded is programmed (on the backend) and how the changes you
make after it’s loaded are programmed. This leads to a lot of weird
inconsistency if you’re doing anything more than showing and hiding existing
content. Also, with jquery everything involves a lot of imperative programming
and stashing state in random places in the DOM. If you’re doing anything more
complex than drop downs and modal windows, use a frontend framework or your
code will devolve into a huge pile of spaghetti.

~~~
mythrwy
It's not necessarily the case that jQuery code devolves into a huge pile of
spaghetti. It's very possible to stay organized without a framework, even for
fairly sizable JavaScript apps. It takes a bit of foresight and thinking ahead
and discipline, (usually resulting from having written piles of spaghetti in
the past). But most large jQuery in the wild is indeed spaghetti, with that I
will concur.

~~~
woah
Yea, you can write your own framework to avoid it becoming spaghetti. But most
developers are going to mess it up. I've seen a lot of bad jquery apps and a
lot of bad react apps. The bad react apps, they might be hard to understand,
but at least they behave consistently.

------
Mc_Big_G
Without any input from me and several other js devs in our org, it was decided
that we'll do a complete rewrite of our Ember.js app in React. The primary
reason stated was hiring and the secondary was build times. The first should
have been performance but they've been pretending like performance doesn't
matter and that it's good enough. It's not.

Since it's easier to develop, our backend admin system is built in .NET's MVC
framework and it's lightning fast compared to our frontend. Like ridiculously
fast. I'm not currently a backend dev but I have extensive experience with
Rails and I've seen the same with Rails. It's fast.

Despite the fact that I'm a front-end dev and it's not in my best interest, my
un-requested recommendation was to do the rewrite in MVC, thus delivering
everything from the server side. Here are my stated reasons:

• The site will load and responds incredibly fast

• The "build time" problem disappears

• The "hiring a lot of specialized javascript developers" problem disappears

• Backend devs suddenly become full-stack devs

• Deploying is easier

• Testing, both automated and manual, is easier

• SEO is easier

• You can now hire junior developers who are productive and don't create a
mess in a new js framework

• It's going to be supported for a long time, unlike the latest javascript-
framework-of-the-day

• Our website is a website full of mostly content and CRUD forms, not an app.

We actually have very little "highly interactive" parts of our site and those
that we do have can be a light-weight framework or simply a sprinkling of
javascript. It should have never been an app in the first place.

If everything had been build in Rails from the beginning, instead of .NET and
Ember, we would have been twice as productive with half as many developers and
wouldn't need QA at all if we wrote tests.

This opinion was basically scoffed at with no valid counter-arguments given.
They will move forward with a complete rewrite in React, which will solve none
of their problems, except MAYBE hiring, and likely create more. They'll also
probably do it without me. I'm not against SPAs or React when used for the
correct reasons, especially considering I've been focused on front-end for the
last 5 years, but I am vehemently opposed to bad decision making.

~~~
korm
I think if the conversion is led by a very experienced React developer this
could be a good decision. We decided to write all our sites in React a long
time ago and couldn't be happier. It doesn't have to be a SPA because it's
React, we have static sites too.

Judging by how your org made the decision without the devs input though, I'm
not too confident it won't be disaster. It's depressing but I've been offered
too many contracting opportunities to rescue a project after a similar
conversion that is a total dumpster fire.

~~~
Mc_Big_G
No one on the team has ever used React.

------
3pt14159
I was initially skeptical, but this article nails the issues 100%. His
experience mirrors my own and I don't think I even had a single place where I
disagreed with him.

All I would add is that rails can be made to work wonderfully with SPAs if
you're willing to do some metamagical programming to auto-follow standards
like JSON API.

------
Illniyar
Replacing the entire body with every request seems a bit overkill. If you want
SPA interactivity without moving control to the client side, try
intercooler.js

[http://intercoolerjs.org](http://intercoolerjs.org)

------
meesterdude
A very well thought out and articulated article.

I love Rails and the power it offers in development productivity and quality.
It's code is very maintainable and actually enjoyable to develop in; even when
it's someone elses codebase.

Oddly enough, I finally came upon a use case in a project where an SPA
frontend (Vue) / ruby backend make more sense given the platform nature and
operational needs (runs on a pi, no "models")

9/10 Rails is the way to go though for developing something.

------
ransom1538
Has anyone used jquery mobile?

It was an amazing project that let you write normal css/html/js without
modifications THEN rendered the html+js into a SPA. It was fast, preloaded
pages, clean, easy to write and really well documented - and maintained the
root dom element. BUT! The project is mainly(opinion) dead. Instead people
want to write in a new language (react,vue,etc) then deal with adding a
massive layer of complexity.

~~~
FreakyT
I dunno, my experience was that JQuery mobile was slow, bloated, and glitchy.

Perhaps it was simply ahead of its time, and 2011-era browsers couldn't keep
up with it, but either way I much prefer using its successors.

~~~
zdragnar
This is the first time I've ever heard of jquery mobile described as fast, and
I used to work for a medium sized consultancy / agency (as in upwards of 50
front-end devs) that did a lot of projects with it.

In fact, I don't really recall anyone speaking positively at all; at best it
was a necessary evil.

------
fred123
I wonder how the argument changes if you know you need an API for your mobile
application that's almost identical in features to the web page.

If you go the "Rails/Django way" with server side rendered templates and, say,
a bit of jQuery for fancy stuff -- you'll end up duplicating lots of code for
the API (validation, routing, maybe even business logic).

Anyone got experience with swapping your models/controllers for an API while
keeping the rest of Django's/Rails' niceties? (authentication/sessions,
Django's forms system, CSRF, etc.)

OTOH having Django/Rails merely as a template system you probably could also
go for very simple, self-contained client-rendered JS pages (e.g. .vue files).
Not much difference there I guess?

~~~
noxecanexx
I think it should still be possible to seperate view from the service at the
backend, even if that means defining more routes. I am talking from the
hiccup(clj) point of view though

------
stevebmark
Rails is a deeply flawed framework, and we need to stop using Basecamp as the
example of a well designed monolith. Basecamp is terrible software, and the
crappiness of the user interface appears to be a direct result of not being
able to build rich interfaces as its coupled to legacy Rails designs like this
article suggests. Basecamp being fast while getting a trickle of traffic and
working with very little data is not a selling point against SPAs (I'm not pro
or con SPA).

~~~
rimliu
What are the deep flaws in Rails? What's crappy about Basecamp UI?

------
randop
I feel like seeing more and more post about criticisms for workflow or
framework that it is becoming unhealthy with the developer community.

There is always short comings on every tool and library, and part of
responsibility of a good developer is discerning trade-offs.

------
PythonicAlpha
The main problems addressed in my opinion:

\- Code duplication between server and client side

\- Added complication threw data transmission between server and client
(REST/json)

I think, both problems can be addressed by:

\- having (a single) code that works both on server and client-side

\- having transparent transport mechanisms for information between client and
server.

I am sure, I could implement such a thing for Python/Django, using the already
existing tools. But I am not sure, if such a thing would be appreciated by the
community.

What do you think?

------
arwhatever
Using a framework like the F#-to-JavaScript transpiler Fable, along with an
application framework like Elmish, provides a really good solution to some of
the pitfalls cited in the article (prescriptive architecture, front + back-end
code sharing) and gives you some moderately strong type safety to boot.

However, the article author's list of SPA pitfalls is really good, and are
probably not all surmountable by a framework/platform.

------
everdev
Anyone have good experiences with an SPA architecture?

~~~
kkrs
Elm + Scala works for me. I'm using the same elm source with minor variations
for both web & mobile (wrapped with cordova). So far, it's been working
wonderfully.

~~~
virtualwhys
That's an odd choice given Scala.js, any reason you're not all-in on Scala?

~~~
kkrs
The elm architecture removes the need to make decisions when it comes to
structuring the app. The tooling is first class. While I'm not sure, I think
elm has a larger community.

------
cmjqol
Like others comments , Kudos to the authors.

I'm an SPA Lover ( Angular , Vue ) , but still most of the points raised here
a coherent from a back end perspective.

That said , a lot of the arguments are basically summed up as :

"I don't like Front End Dev. because it's not as mature as Back End".

I will not lie on this point , JS is a fast evolving ecosystem that sometimes
has issues to stabilize. Hence , there is a lot of marketing and self
promotion mixed with frameworks sometimes ( Growth Hacking ) pushing for
unnecessary tech that dies a few days after they have leaved the Github
Trending page.

For beginners , when a framework reach a certain threshold ( Github Stars most
of the time) they feel like they should hurry and use the framework to stay
relevant while most of the time they don't need to and the tech is just fluff.

My point here is very simple, you are ROR or Django or ASP.NET dev and you
love what you do ? As long as you find jobs keep doing this , don't bother
with Full Stack Fluff.

Now that said , I can only encourage the author to do the Angular or Vue
tutorial to discover something different. Rails is great ( it's empowering a
lot of website Github , Airbnb etc... ) but SPA are different and when used
properly it's hard to go back , the experience is delightful.

Most importantly we are getting closer to the serverless era where backend
will be completly different from what it is compared as now, and SPA and SSR
will likely be the standard in the future.

~~~
sho
I think you've missed the article's point:

> I don't like Front End Dev. because it's not as mature as Back End

No, he says don't do FE _and_ BE when the tools for back end-only (well, Rails
is full stack, actually) are so useful and productive. And in the rest of your
comment you seem to forget that a front end is completely useless without a
back end.

> you are ROR or Django or ASP.NET dev and you love what you do ? As long as
> you find jobs keep doing this , don't bother with Full Stack Fluff.

Rails _is_ the "Full Stack Fluff".

> SPA and SSR will likely be the standard in the future

How, exactly? What serves your SPA? And who is using "serverless" for anything
other than querying other backends (eg Slack bots) or accessing AWS services?
I mean, sure, it's nice to not have to stand up a server to resize images
coming from S3 but it's hardly going to replace, well, servers. You couldn't
implement even the simplest CRUD app.

~~~
SpaceNugget
Uh, you can definitely implement a standard CRUD app with one of the
serverless platforms. You can even throw an entire expressjs application into
a lambda function with minimal modification if you want.

~~~
cmjqol
> You can even throw an entire expressjs application into a lambda function

This is the first general misconception with serverless.

Serverless is not lambda . If you think serverless == lambda, it's like saying
cloud == ec2 . You're missing the point of it.

~~~
y4mi
than please define serverless for us.

using lambda and its equivalent is - in my understanding - the definition of
serverless. You might not be able to utilize the biggest advantages of
serverless infrastructure if you combine it with a standard ACID database
backend, but it should still be a serverless deployment.

------
swlkr
I had this same experience. SPAs, especially for small teams and solo
developers, hurt more than they help.

------
cutler
Turbolinks to the rescue. Slay the Javascript overlords!

------
Bizarro
There was probably a few valid points, but the article was too long with too
many flimsy, "try-hard to convince" arguments.

------
_pdp_
Speaking of code duplication in a traditional web app every page is an example
of code duplication. How about that?

