3 ms·
The js ecosystem is frustrating. I’m a backend/DevOps/platform engineer so I don’t write frontends, but I’ve spent many hours working with and optimizing the co
by ransackdev 3y ago
The js ecosystem is frustrating. I’m a backend/DevOps/platform engineer so I don’t write frontends, but I’ve spent many hours working with and optimizing the compiled JavaScript in CI/CD pipelines, deployment systems, and homebrew bespoke SSR Rube Goldberg micro services that a backend calls out to, waits for the js to comeback, throws in a redis cache, then sends down the pipe to the user. The frustrating part is that often times the clusterfuck required to spit out some scripts that make Ajax calls to a backend, shuffle divs around, bind dom events, and push browser state, is so much more complicated than the backend systems that are actually doing the core work for the app.
SSR was a solved problem before SPA/huge frameworks became the often unnecessary de facto, standard. Why am I dealing with a backend app server that is deadlocked and exhausted its connection pool causing cascading failure because its (wrongly) making in-band calls to a micro service someone wrote which is a single threaded node app running a virtual dom and spitting out js that shouldn’t be required to serve up the app’s presentation layer, yet now is queuing up an ever increasing buffer of connections from the backend trying to get the page assembled to send to the user who does not care about any of the js so long as when they click shit, it clicks.
Js is a simple and small language. The runtime it executes in is designed for a very specific deployment target and even there it’s at its limits. Why did we let a tiny scripting language become this beast of complexity and obnoxiousness? Why can I put bundle optimization and tree shaking on my resume? Or that I inherited and maintained a not invented here fueled SSR system that would rehydrate Apollo stores and glamorous styles, for a site that would have looked the same and provided the same FE functionality using bootstrap css and js? Why am I adding extra headers to response bodies to debug if SSR is being cached by the backend properly, or if the caches are being busted properly and sweeping down the Russian doll layers at the react component level? Why, if it was known from the start that search crawlers wouldn’t render JavaScript, and as a result wouldn’t render the content you want indexed, did you not use a friggin backend templating engine that every MVC framework has a million options for, and include a damn partial that adds your js for a signup modal and some Apollo gql queries? All this complexity is for what? Bash is a tiny scripting language with very specific deployment targets and handles mostly presentation and in the what, 60 years it’s existed, shipping a shell script has been as simple as scp’ing a file to a server, which is how easily you used to be able to “build” and ship js. If the Linux OS devs didn’t need that kind of complexity, your hot or not site doesn’t either (: Is your job as a front end developer significantly improved from the days of using jquery or some other tiny no nonsense utility lib? I see the js being written and I don’t see a huge quality of life improvement to justify the chaos these systems introduced to the entire stack, build system, CI system, deployment orchestration, bundle optimization, library bloat and security upkeep, dependency hell for package upgrades, CVE shit show and supply chain security. What is your app doing that all of this is needed, for presentation? Modern web apps are enormous, render slow as hell, and often break expectations set in stone 20+ years ago, like the back button doing what it says on the tin, or inspecting a dom element and being able to actually see the content, not off in some store somewhere and bound to some property event that injects it and removes it as needed.
People have just accepted that this is how FE dev is done now, with jr devs knowing only this insanity and not anything else. I try to delude myself to think that this is fine, it’s better, somehow, and yes I realize that modern frameworks are in some ways better, react components are modular, reusable, transpilers are able to do chunking, lazy loading, tree shaking, gzipping, and compile time performance optimization as it writes the file, but why is this needed for a single threaded language primarily doing network IO and string replaces? Nobody on the FE team at that place with this insanity could grok how it worked, and didn’t understand when things rendered with SSR would be different, or how to debug any of at all. They didn’t run SSR locally to confirm, they didn’t use any tests, and trying to force them to model the request flow between backend micro services, the added complexity of any caching solution, to constantly be mindful of not having access to the window element when running in node server side without special consideration for shims or null objects, is not fair to them, but it’s not fair for people familiar with deploying complex backend SOA systems to be force fed a maintenance and stability nightmare either. There has to be a common ground.
I know my rant is exaggerated and overly critical, but god damn y’all, reel it in a bit, will you? I’m hopeful that things get slimmed down and less complex as the JS community corrects for the over correction that caused all of this and got us here, and I see things that tell me it is happening, so hopefully soon my job won’t have to mentally model and reason about these moving pieces that result in static files on a cdn.
If I can ever finish it, my solution to end the need for SSR at the lib level, which isn’t original by any means, was a background queue, and a pool of headless chrome docker containers that handled it all. Send it a url, the page is rendered in real chrome, guaranteeing runtime compatibility, dev tools api calls will execute some js in chrome console to inline styles and prepare the js, and finally spit out a full html page complete with bundled inline styles and JavaScript, along with any rehydration on load events. No need to have special js packages or servers. No need to think about it at all as a FE dev. If it works locally in chrome for you, it’ll be the same thing from SSR. Some middleware in the backend app to route crawler/logged out/whatever you want requests back to the SSR system if not in cache, serve from cache if in cache, or pass down the call chain and let the backend serve up html with client rendered js if it’s a request you don’t want SSR’d. Still complex but the core of it works for any and all websites, not just one with a special SSR js package and config. For shops with many apps and frontends, it could all run through the same chrome ssr render pool, because it’s just a bunch of sandboxes chrome instances.
Note: it’s been a minute since I’ve been in engineering at all (out of work) so things may be much better now. I also am fully aware that the SSR system of insanity I described above was overly complex from the day it was built, and nowadays many frameworks ship with bundled SSR functionality.
- flimsypremise 3y agoAs someone who has been doing frontend, backend, systems administration and general black magic since before the jquery days, I can tell you that managing frontend requirements was absolute hell back then. You literally had to put the script and style tags in the right order in your header or footer and just kind of hope the timing worked out. People how work exclusively on the backend tend to underestimate the complexity of frontend builds in the same way that non-technical people underestimate the complexity of all software engineering. The truth is, something as common as an autocomplete input is an application unto itself, with multiple dependencies all with load priorities. I don't have to imagine what this was like back in the jquery era, because I experienced it and it sucked. I noted this earlier in the thread, but the fact is that any user-facing application with a UI is going to include JS/TS and CSS, and therefore is going to include a frontend build of some kind. Any build included in an application comes with the requisite build orchestration for all environments, so Docker config, build specific config, CI config, etc. If you add a second language to an application, you add a second build, and the cost of setup and maintenance of your application basically doubles. Not only that, you now have to have engineers proficient in multiple languages on your build. Most engineers are really haughty about the language they write and the part of the codebase they prefer to work on, so finding someone who is equally comfortable AND proficient writing python applications and frontend code is extremely hard. Most likely you'll get a Python engineer who will reluctantly write some awful React and complain about the entire time, or vice versa. So if you come to me and try to add some Python or Ruby or god help you PHP to my single build Node/React application because you think its somehow going to make things simpler, I will simply eject you into the sun. I'll write an API in any language that makes sense for the performance requirements. But if the app has a UI, absent any legacy requirements that force you to do otherwise, it 100% absolutely has to be entirely in JS or TS or you are shooting yourself in the foot.