I have been intending to move my writing off of Medium for a while now, and while I haven't put in the work to move old posts away, I'm at least starting to explore other platforms. Dev.to is the one everyone is recommending now, so I signed up and started to try to write a post here.
I'd still like to write that post (and I'll publish it next time), but it'll have to wait -- I have to write about Dev.to right now first and its inspiration for myself.
Dev.to is Fast
It is insane. Dev.to is capital-F Fast. It's so fast that it feels like a local web app, not one on the internet. I was exposed to Dev.to a long time ago but it had always been one-off articles, so the speed is less noticeable; when I actually went through to sign up for an account, edit my profile, etc. I noticed how ridiculously fast it is.
My immediate thought was, what is Dev.to doing right that pretty much every other site on the internet right now is doing wrong? How can they be so fast? By comparison, it makes the sites of even internet giants (Reddit, Github, and even Hacker News!) feel like turtles. And it's not like Dev.to is small -- Alexa reports it at around the 8000~ range in global ranking (compared to HackerNoon at 4000~ or npmjs at 6000~ or so), and there's tons of content!
Digging into it, it's a traditional Rails site with InstantClick
I first started by viewing source and opening Chrome Dev Tools; and noticed that every page had full HTML rendered so it didn't seem like a React (or any other frontend framework) site. Then I noticed that whenever I hover any links, it sends a request to preload pages. I knew of a JS library called Turbolinks that did that, so I thought that might be it.
Then I noticed the Dev.to site code is open source, so I checked it out and found its tech stack page and saw that InstantClick was the secret sauce. It works exactly as I observed -- it preloads the HTML output of hyperlinks as you hover them, and replaces the current page's HTML when you click on them, and adds some history.pushState()
for good measure.
This is the model content-based web apps should strive for
Let's face it, big orgs/startups that manage content-based web sites with a modest amount of functionality/business logic almost always default to React for a frontend framework. Organizationally this makes sense, you have a big dev team working on the product, and a component-based frontend architecture is the most sensible way to work together on a big frontend codebase.
But is it the best UX? One doesn't need to venture far from your typical popular media sites (Techcrunch, ESPN, etc.) to see them doing React or React-like behaviors -- your typical server-side-rendering of the first page, loading a JS bundle, hydrating the app on client JS framework, and then the next pages load in API calls, etc.
In contrast, Dev.to simply prints the output HTML of the page from the server at each server endpoint, and it's only boosted by InstantClick preloading the page when you hover the links (and subsequently the new HTML replacing the current HTML to prevent a full browser page navigation). I argue that this is the model content-based sites, content-based web apps, including blogs, e-commerce web sites, etc. should be using in their development.
Why does this make sense?
We, as the whole tech industry, spent a decade (roughly from 2007 to 2017 or so) optimizing every part of the server side of web apps -- everything ranging from database performance (techniques like read replicas, sharding, and newer and newer generations of DB engines), caching (memcache, Redis, local web server caching), asynchronous work queues for writing data, loadbalancers and infinitely scaling web servers (with the advent of AWS), regions/availability zones and edge CDNs to be closer to users.
Once we have everything, we really proceeded to nullify all that investment in server side performance optimization by putting a heavyweight frontend framework like React on the client side to work with those servers. Now to load a web site you need to load a 1mb JS bundle, have a spinner on the first page load of your site or web app, and let React handle this whole virtual DOM and calculate how to render everything at every point in time when anything changes states. We're right back to where we were in the 2000s when web sites/web apps were slow, when it was because we didn't have all those server side technologies and consumer internet connections were slow. Web sites take a few seconds to load now, just as it did in 2007; but for entirely different reasons. Isn't it a little sad for the end user, with all the advancement of technologies, the user experience stayed roughly the same (or worse)?
But, component-based frontend development!
Honestly, as someone who's not a fan of React, the only valid argument I agree with for doing a React frontend (and this is a huge one) is the organizational reason. In my 15 years of working in software teams, component-based frontend is really the most sensible way for a big team to work on a frontend codebase together and scale a frontend codebase; there's no way around it.
Traditional MVC frameworks with templated views make it entirely too difficult to have any reasonable re-use of frontend code without some frankenstein monstrosity; and scaling a jquery frontend inevitably leads to spaghetti code. I believe it's one of the primary reasons React has taken off in tech startups; it's the best way to grow a dev team to work on frontend seriously.
Maybe a new development paradigm is in order?
How can we take advantage of server side generated HTML outputs in a web app, but also take advantage of component-based frontend development? Here's something I came up with literally just tonight, perhaps this could inspire you to try something similar?
- Frontend team develops in component-based framework of choice (React, Vue, Svelte, etc.).
- Frontend toolchain to build static HTML of each page based on components (This build happens both locally during development and on CI tool as well) -- this can continue to use Webpack, Rollup, or whatever folks prefer.
- Each built page takes in set of variables (similar to how templated views work in traditional MVC web apps).
- Frontend can mock this backend-provided data similar to how it mocks API responses for React frontends during development.
- Backend uses a traditional MVC architecture, with any language (Ruby, PHP, Python, Nodejs) and framework (Rails, Laravel, Django, CodeIgniter) of choice.
- Backend renders views by loading those prebuilt static HTML by page name, and passes in variables just as it does for templated views.
- Feature development workflow: Backend and frontend team members work on same branch for a feature, each check in their changes independently, when frontend checks in the components source code, CI tool runs the build toolchain and the generated static HTML for each view is then committed into repo as well.
- Frontend can continue to organize code in a similar React monorepo as they do right now, with reusable components and everything.
- Don't get me wrong, your React components can still react to clicks, moves, etc. and change states locally, you are free to still make AJAX requests in many valid use cases of it. All of that doesn't change. But page navigation should be left to
<a href>
and InstantClick and the server to generate the next page, when it's an entire page change.
Your thoughts?
I haven't given this work flow any more thoughts than it took to just write it all down, so curious to hear opinions of others.
Top comments (20)
I approve this message.
There is definitely a case to be made that trading bandwidth for performance is a winning exchange for desktop users with big pipes and no data caps.
I don't think people with data caps on their mobile plan will appreciate all the their minutes disappearing though, which I guess doesn't matter because how do you even optimize preloading with no hover selector on mobile?
On mobile devices, preloading starts on βtouchstartβ, giving 300 ms (Android) to 450 ms (iOS) for preloading the page.
Thank you for clarifying
I think what you are describing at the end is Next.ja, you use React to build your app, then you can either generate the HTML at build time or at runtime querying the DB (or an API) directly, you can then leverage HTTP and CDN cache, it will also prefetch the code for new pages when you hover them.
I second this, this is the problem Next.js intends to solve with SSR, which gives an edge with SEO over standard CSR solutions.
I agree with this article because I'm tired of loading times with CSR's, it kills me a little bit inside every time. I don't know how people can be so blind or have so much patient.
Hi Kenny, great to see you here! And hello Sergio!
My understanding of next.js is that it handles SSR and React routing. I think this is different than what I have in mind, which is essentially static-site-generation (but not to final HTML output, but to templated views for MVC).
The conceptual difference is this: SSR is still rendering the output HTML in real time (only in server side code, instead of client side). It still takes server resource to do this on-demand. SSG (static site generation) is sort of what the JAM stack is about -- you pregenerate HTML from your React/Vue/Svelte frontend components, and it simply lives as static HTML files on the web server (and in the case of JAM, they talk to an API server afterwards). In the case of what I propose, they are rendered as templated views, where an MVC framework could just call
render(pagename, variables);
at the end of a controller to render the view.Perhaps I would need to run some benchmark to know if there's actually significant performance improvements to gain at all. Like I said, I spent no more time than what it took to write down the thoughts, to think about it, so more work is warranted. :)
This article might interest you Bigi. It talks about the frontend stack including InstantClick.
dev.toβs Frontend: a brain dump in one act
Nick Taylor (he/him) γ» Apr 23 '19 γ» 8 min read
I wrote it before I started working at DEV and I believe it was my now co-worker @jacobherrington that integrated parts of that article into the DEV docs . Since starting at DEV Iβve also updated the docs related to the frontend, including webpacker 4 upgrades.
Other things that we do in the frontend to make things faster are leveraging service workers as well as dynamic imports. You can dynamic see imports in action in for example the onboarding process or the logged on feed.
In regards to reusable components, we use Preact components mainly for the logged on experience. The only exception to this I believe is search.
Something that I would like to experiment with during the next cooldown period or the following one is server-side rendering Preact components in a Rails app as it is possible. I put the question out on Twitter and the creator of Preact, @_developit chimed in that it was possible.
@ben also has some great posts about making DEV fast.
Making dev.to Incredibly fast
Ben Halpern γ» Feb 2 '17 γ» 5 min read
What it Takes to Render a Complex Web App in Milliseconds
Ben Halpern γ» Aug 18 '17 γ» 4 min read
Instant Webpages and Terabytes of Data Savings Through the Magic of Service Workers β¨
Ben Halpern γ» Dec 18 '19 γ» 5 min read
Thanks for showing DEV some love and looking forward to your next article! ππ»
Great links! Just finished reading the frontend brain dump, planning to read the others as well.
Thank you so much for using React/Preact in various modules of the site dispersed in different places, instead of a SPA. I believe this is the right way to go for content-based web apps. Too many tech startups default to React and SPA just because that's what everyone else is doing, and perhaps in some ways it's "easier" to just go full SPA when you already want to use React (for organizational and team-scaling reasons). When React modules are small and separate on a page, they are really snappy. When it's a SPA and entire pages changes, it feels way more sluggish than what you do with Instant Click and HTML outputs from server. I wish what you do is the standard across the web among content sites.
As someone using exactly none of the above - dotNET Core with no JS frameworks at all - even I see potential immediate benefits from InstantClick-like acceleration. The frontend is about as simple as these things get: one main CSS and JS file alongside a few helpers, so adding something like this is probably easier. Thanks for posting!
That new paradigm might already exists. I use unpoly.com/ which together with any server side templating that allows you to componetize your markup (I use my own JavaScript template string based wrapper npmjs.com/package/html-string ) makes a very productive stack. And it's faster than any spa framework I've ever used.
Very nice, I had not heard of Unpoly before. Reading the "How it works" and skimming through some of what it does, it reminds me of what Intercooler.js does. It's also a lib I always meant to try on a project but never got a chance to.
Intercooler.js has now a jquery free sibling called htmx htmx.org/
Another similar lib is Trimming postlight.github.io/trimmings/
Any tutorial on how to add InstantClick to a rails app? I added it to my Javascript packs, but somehow I get an
InstantClick is not defined
error in console. Do you have to do anything to disable Turbolinks when adding InstantClick? Thanks.Issue described here: stackoverflow.com/questions/611164...
I have to admit that dev.to is so fast that it sometimes borders to annoying me. I kid you not, I keep wondering how the heck they manage to load an online page faster than I can load local html pages.
This is the sort of thing that might already be proposed as a feature on the GitHub for dev.to - since it is open-source after all, you can even suggest things yourself. How cool is that?
Totally agree. How is dev.to so fast? Unbelievable even in Seoul, Korea.
Korea's average internet speeds are fastest in the world as of the last stats I checked, which makes dev.to's speed even more remarkable!