5 ms·
SPAs are the "Google-scale" of frontend tech. YAGNI unless you are Big (or trying to fleece VCs). SPAs are useful where the latency and overall UX of a button
by pphysch 5y ago
SPAs are the "Google-scale" of frontend tech. YAGNI unless you are Big (or trying to fleece VCs).
SPAs are useful where the latency and overall UX of a button press can be translated to some tiny % increase in a KPI through A/B testing, etc. Where you want to track user behavior down to a pixel & microsecond, and wrapping every element in JS is the only way to get there. This is frankly irrelevant to 99% of projects and companies.
SPAs are not designed for developer productivity, they are designed by BigCo that can spend 0.01% of their revenue to hire multiple teams/ICs to squeeze out a +0.1% increase in revenue. It's comparable to doing microarchitecture-specific optimizations for your clientside website code. Totally irrelevant to your side project or startup.
Pick a productive stack/framework and build out your product with a solid foundation. You can always bolt on websocket-based features as required. Maybe rewrite your frontend in a SPA framework once you hit $100mm revenue.
- funklute 5y ago> SPAs are not designed for developer productivity Unless your app is big enough to have separate developers/teams for backend and frontend. In this case I'm relatively convinced by the argument that it allows you to decouple the two, so that all they need to agree on is the API. Do you disagree? If so, how come?
- bauerd 5y agoHave you tried to implement interaction-rich applications such as calendars or text editors with server-side rendering? You won't be able to recreate the UX an SPA can afford, regardless of revenue.
- pphysch 5y agoYes, I have. With a proper backend language like Go it is trivial to manage concurrent WebSockets and arbitrary data across them.
- jrockway 5y agoOn whatever page you're using websockets, you're basically doing what an SPA does. If you click something and the page sends and receives a message via websockets and then updates the DOM, congratulations, you have something that's the same level of complexity as a SPA. Your original post says that this style of interaction only exists to "fleece VCs". But it seems you're doing that, with an additional added layer of complexity on top (namely the server-rendered pages). I'm guessing you implement the interactivity with <script> tags or something in your html/template templates, skipping the pain of npm and bundlers. I'm not sure that's the hard part of SPAs, though. Just an annoying one. The hard part is synchronizing the state of the frontend and backend over a communications channel.
- pphysch 5y agoAnd SQLite is "basically" doing what Hadoop does. Except not really, because one is architecturally simple and relatively easy to grok/hack, and the other is big and complex and built specifically for operating at a massive scale and multi-team environment. We're talking ~200 combined LOC of idiomatic Go+TS & a couple popular libraries vs. an entire SPA framework and its various DSLs. State synchronization over a long distance is always going to be a balancing act of performance vs. reliability vs. security. It's never simple and outsourcing those decisions to a framework is not always the correct choice as it may bite you later.
- ubercore 5y agoThis sounds more complicated to me than just using React plus an API backend.
- 1_player 5y agoWidgets require JS, of course. Javascript was born to sprinkle some of it on top of an HTML page, not to make a whole meal out of it. This is what GP is arguing about and I tend to agree. Single Page Apps are not worth the effort in my experience, apart from very niche use cases. The velocity proposition and fantastic developer experience of writing JS in the backend and frontend and data layer is overrated and misleading. It's everything but.
- robertoandred 5y ago"Sprinkling" JS means you end up with a messy mix and match of markup on the frontend and backend, inconsistent behavior, etc.
- jack_riminton 5y agoNot always. The Rails ‘stack’ has a preference for StimulusJs which has a nicely ordered way of sprinkling the JS. No inconsistency there
- YuukiRey 5y agoI don't think anyone would take fault with using a SPA for a text editor. What most people are criticizing is using a SPA for a page that serves mostly non-interactive content. And that is the majority of the web, after all.
- tiborsaas 5y agoI can build SPA-s on my own. Based on your assessment, should I ask for infinite salary since my work is Google scale?
- pphysch 5y agoYou can also deploy Hadoop on your own, or write platform-specific assembly on your own, but the question remains: is it worth it?
- tiborsaas 5y agoI've also developed lots of server side generated webapps (edit: websites) and I still like the SPA approach more because it's more clean and domains are better separated. So the answer is usually yes, to me it's worth it if the problem requires SPA. You make it sound like SPA-s are like the Death star, but this is really far from the truth.
- continuational 5y agoI mostly agree, but it's very nice for the x% of your application that is real-time interactive. In some cases, x is high, such as Figma.
- clement_b 5y agoThis comment should be printed and put up on quite a few teams' wall.
- jeremyjh 5y agoIt doesn't cite any evidence or sources, it just declares the opinion of one person on the internet as if they are facts. Who do think would be convinced by this that doesn't already agree?
- jeremyjh 5y agoYeah. I've done the server-side thing quite a lot. I don't like it. You always end up with "little bits" of javascript code strewn about in your DOM doing adhoc manipulations based on user events, server data arriving etc., and so the actual behaviour of your app is more difficult to reason about. Also, I want my users to have a nice experience and enjoy using the app, even if I don't have a KPI to represent that benefit. And until quite recently that was much easier to do in a modern SPA framework. I think the newer hybrid approaches like Phoenix LiveView give you the best of both worlds though.
- pphysch 5y agoI don't follow this logic. Why do you end up with JS strewn everywhere? Sounds like poor organization practices. 1. User arrives at a page where a real-time widget may exist. <src> widgets/mywidget.js on that page. 2. User triggers mywidget.js by pressing a button or just existing. It dynamically creates the widget elements, requests a secure websocket, then sets up input/output handlers. 3. Done. mywidget.js could be big and sophisticated -- a multiplayer video game, for instance -- but it is certainly not "strewn everywhere".
- jeremyjh 5y agoI'm not talking about how my javascript source files are organized, I'm talking about how the functions are dispatched from the UI. That is done with event listeners strewn about in the DOM.
- pphysch 5y agoWhat is so complicated about <input id="initMyWidget" type="button" value="Play" onclick="mywidget.initGame();"/> If you are referring to "the page is the widget" then you need to make a very good case why wrapping all the HTML in JS is in your interest. Facebook has an interest in doing this because they want to wrap every element in a bit of JS so they can closely track user behavior. Briefly hovering over a link, button or ad? Facebook wants to know everything about that interaction, in order to provide value to their clients (i.e. advertisers). A normal developer is happy with that element just being a `<a>` or `<input>`. The entire page does not need to be a JS widget (SPA).
- mattferderer 5y agoIn my experience as a user, these SPAs built by very large companies for a very large audience seem to be full of bugs & issues when they try to do to much. Something like a music player seems to work great as a SPA. But something more complicated like Google AdWords or large financial apps & you're bound to run into issues often.
- brimble 5y ago> SPAs are useful where the latency and overall UX of a button press can be translated to some tiny % increase in a KPI through A/B testing, etc. This is frankly irrelevant to 99% of projects and companies. And even so, I can't think of a single example in which there are two versions of a service and the one that almost never reloads the page feels faster than the one that reloads on practically every action. In fact, the last time I recall seeing a large web-app sort of product that made me go "holy shit, that's so snappy I can hardly believe it's actually doing anything, but it is", it was... written in PHP and reloaded the page damn near every time you clicked anything.
- BenoitEssiambre 5y agoSPA's need not be complex nowadays. I use https://lit.dev https://lit.dev 's templating engine. When I want something simple, I use just the templating engine not the full web component framework. Lit's templating engine is just html that is made super efficient to render because only parts that change are re-rendered. There is no inter language to learn like JSX. It uses native browser html parser, native browser templating capabilities (<template> tag), native event handling and native literal template capabilities of javascript. I have a simple wrapper class that renders and composes components efficiently and reactively when state changes. The views look like: class TestView extends LittleLit { static get properties() { return { paramter: {} }; } constructor(){ super(); this.el=document.querySelector('#main');//root component attached to the dom this.subcomponent=new SomeView(); } render(){ this.subcomponent.somestate=this.somestate;//propagate state down if necessary. let h=html`<H1>Hellow ${parameter}</H1>${subcomponent.el}`; render(h, this.el,{host:this}); } } To use v=new TestView(); v.parameter='world';//this triggers rendering if the parameter changed. Here is my whole framework: class LittleLit { constructor() { this.el=document.createElement("div"); this.refreshScheduled=false; this._properties={}; let properties =this.constructor.properties; if(properties!==undefined){ for (let prop in properties) { this.property(prop,properties[prop]); } } } refresh(){ //you can call refresh to trigger rendering efficiently if(this.refreshScheduled===false){ this.refreshScheduled=true; window.queueMicrotask(()=>this._update());//deduplicated rendering in an efficiently scheduled microtask } } _update(){ this.render(); this.refreshScheduled=false; } property(name,options){ Object.defineProperty(this, name, { set(v){ if(this._properties!==v){ //refresh only if property changed this._properties[name]=v; this.refresh(); } }, get(){return this._properties[name];} }); } } Most of the power comes from the templating library: https://lit.dev/docs/templates/overview/ https://lit.dev/docs/templates/overview/
- mmargerum 5y agoVue/React/Svelte are pretty damned productive. 1/5 - 1/10th of typical server rendered or native UI LOC. If I never write another line of code directly manipulating UI controls I can die a happy man.