17 ms·
The problem is not so much React as it is the JS ecosystem, but React is just very visible when you have these issues because there are so so so many packages b
by mark242 2y ago
The problem is not so much React as it is the JS ecosystem, but React is just very visible when you have these issues because there are so so so many packages being imported.
And the root of the problem is peer dependencies and the JS community's lack of backwards compatibility and maintenance.
Take any decently-sized JS application, whether React or whatever else. Put it in Github. Turn on dependabot. Watch your pull requests go up by 5-10 PRs per week, just to bump minor versions, and then watch how 1 of those PRs, every single time, fails because of a peer dependency on a lower version.
This has been a problem forever in the community, and there's no good solution. There's also just no feasible way to make a solution due to the nature of the language and the platform itself. You just have to absorb that problem when you decide to use eg Node for your backend code or React/etc for your frontend code.
- skydhash 2y agoFor node and other technologies like react, I would prefer less, but fatter libraries that could be optimized at compile time. All those micro packages coming from nowhere and getting updated every day is a big pain.
- chrysoprace 2y agoOr better yet, no dependencies! The built-in's for both JavaScript and the browser APIs are getting better and better every day, but people still reach for things like Lodash and Date libraries when the equivalent functions are built into the language and runtime itself.
- solardev 2y agoSome things are easy now, but some things still require multiple lines of code: https://youmightnotneed.com/lodash https://youmightnotneed.com/lodash. If you only need one or two, sure, just write your own, but if you're maintaining a big project... why waste time debugging these common utility functions? You'd basically just be reinventing lodash, but with fewer community eyes and tests on it. Whoever inherits that is gonna need to debug all your util functions when something inevitably goes wrong. Like for _.pickBy(), none of these are very readable (https://stackoverflow.com/questions/54743996/converting-lodashs-pickby-in-to-javascript https://stackoverflow.com/questions/54743996/converting-loda...), another implements it wrong and leaves out the predicate (https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore?tab=readme-ov-file#_pickby https://github.com/you-dont-need/You-Dont-Need-Lodash-Unders...), etc. Why do this to your project and fellow devs when it can easily be a single tree-shaken function imported from a popular, well-maintained lib? If anything, ECMA should just absorb more lodash functions into the standard lib, like they've gradually done with some of the array functions. But common things like that shouldn't be up to each individual programmer & team to reinvent all the time. It just needlessly expands the maintenance surface and causes subtle bugs across teams & projects. JS Date is in an even worse place. If you ever need to work across time zones on both the server and the client/browser, native JS date is totally unusable because it "loses" the original time zone string and just coerces everything into (basically) utc milliseconds. The Temporal API is supposed to fix that, but I've been waiting for that for nearly a decade: https://tc39.es/proposal-temporal/docs/ https://tc39.es/proposal-temporal/docs/. That proposal links to https://maggiepint.com/2017/04/09/fixing-javascript-date-getting-started/ https://maggiepint.com/2017/04/09/fixing-javascript-date-get..., which explains some of the weaknesses of the current JS date system.
- chrysoprace 2y agoI agree with you about timezones and I think a library like date-fns (and date-fns-tz) strike a nice balance by not using a bespoke intermediary object type. As you say, some of them are built in and those should just be used instead in most cases. The problem is that when you leave the choice of library to use, then the choice isn't always obvious, especially for niche use cases. A library that's well-maintained today may not be so tomorrow when the maintainer falls ill, gets burnt out on work + open source work or simply gets bored of the project. Deno has the right approach in this regard where they are creating standard libraries to go with their runtime which are expected to be maintained in the long term, but even then I'd still prefer built-in APIs in most cases.
- solardev 2y agoAngular was kinda like that, batteries-included, but it lost to React. It wasn't until Next that we got a similar batteries-included big framework for the React world.
- Cthulhu_ 2y agoBut React was not batteries included, which is where the dependency hell came from; Angular comes with routing, API management, the works, but with React people quickly needed additional dependencies like state management (redux & co), routing, API calling, etc. While Angular feels big and heavy because it's a batteries included framework, React feels simple and quick on the surface, but as the article and the discussion show, it comes with its own price. Angular and React are not directly comparable.
- solardev 2y agoI think we're saying the same thing? :)
- stana 2y agoIsn't that Svelte?
- appplication 2y agoAs a recent convert, svelte has felt wonderful.
- causal 2y agoYeah React itself is actually a very small part of the ecosystem that has evolved alongside React. And it's a mature ecosystem, therefore there's a lot of libraries to use that come at the cost of keeping them patched. It's easy to think that a new tech stack is somehow more complete because there are fewer add-ons and no vulnerabilities have been discovered yet.
- ebiester 2y agoBut here's the thing. It doesn't matter! If I'm building a personal project, I don't have the same time to curate a full ecosystem stack and nobody in the react system is maintaining those for applications that are put to the side for weeks or months at a time. As for me, I just restarted a personal project on rails because of its batteries included mentality - it means I can limit the number of dependencies, and they have gotten very good at migration paths and deprecations.
- alex_lav 2y ago> I just restarted a personal project on rails because of its batteries included mentality - it means I can limit the number of dependencies https://github.com/rails/rails/blob/main/Gemfile.lock https://github.com/rails/rails/blob/main/Gemfile.lock Just a playful comment - not challenging your experience
- frio 2y agoSure, but the framework cares about that for me. I don’t use rails personally but that’s the whole point — someone upstream of me is paying attention and making everything work together. In contrast, I have work apps made in React that need regular piecemeal updating — routers, form libraries, query managers, CSS — because we’ve chosen to cobble that together ourselves. That’s fine, that’s the path we chose knowingly when we picked the tech we picked, but the point isn’t that frameworks don’t have dependencies — it’s that they take on more of the burden of managing them for you.
- solardev 2y agoWell, Next is kinda like that then. It takes care of the sub-dependencies for you and when you upgrade, you just upgrade to the next major Next version (which isn't necessarily easy, but more so than upgrading 100 individual packages). They provide codemods for some stuff too.
- goosejuice 2y ago
- niceice 2y agoIsn't it still a React problem? They could have chosen to not rely on dependencies and you don't have to add more to it.
- Cthulhu_ 2y agoReact itself doesn't have many dependencies at all, but nobody uses React in isolation because it's only a rendering library / data flow; React was never pushed as a full framework.
- jmull 2y agoWell, designing a module to be a peer dependency and then not strongly favoring backwards compatibility is a choice. When you make that choice you're probably screwing your users, in the long run. As a user of modules, if you can detect such module, you can choose not to use it, and save yourself all that future trouble. Now. Let's see. How many times has react's major version number changed?... Yes, it's not only react, but boy are they an enthusiastic leader of this approach.
- tonyhart7 2y agoYeah even when use sveltekit, its still apparent but its still pleasant imo
- qudat 2y agoIt’s not a JS problem, it’s a fundamental constraint of working within the browser runtime: https://bower.sh/my-love-letter-to-front-end-web-development https://bower.sh/my-love-letter-to-front-end-web-development
- goosejuice 2y agoI wouldn't dismiss the responsibility of culture in the JS dependency problem. I agree with a few points in the article but much of these dependencies aren't needed, they are preferred and importing is normalized. Left-pad wasn't a problem because of browser constraints, it was a problem because of culture and to some extent discipline.
- homebrewer 2y agoThis doesn't excuse some authors who enjoy constantly rewriting their libraries just for the hell of it, consistently introducing breaking API changes. react-router might be one of the best examples (or the worst, depends on how you look at it), and it's unfortunately very popular, even though sane and stable alternatives exist (like wouter).
- sriram_malhar 2y agoOP's article complains specifically about wouter's rate of change!
- froddd 2y agoThe main question should always be: why update? Should a library become compromised with a vulnerability, fine (if said vulnerability is relevant to your usage). If you need a feature only available in a newer version, fine (I’m counting better performance as a feature). What I’m seeing far too much of is upgrading for the sake of it. It feels like such a waste of dev time. Pinning dependencies should be absolutely fine.
- llm_trw 2y agoYou either waste your time updating daily or you rewrite from scratch every 3 years. JS is what happens when you let the inmates run the asylum.
- Cthulhu_ 2y agoIn my experience (~10 years of front end stuffs), the rewrite will happen either way. Code rot, sweeping redesigns, obsolescense, or over-eager consultants will trigger a full front-end rewrite / re-architecture every ~5-10 years.
- llm_trw 2y agoYes, but that's 2 to 3 times slower than what happens if you let the code rot.
- cogman10 2y agoThe issue is that feature or vulnerability might not be patched on older versions. If you are using a 2 year old version and a non-backported vuln or needed feature comes along that means you have to absorb 2 years of breaking changes to move to that version. Frequent updates allow you to address the breaks gradually rather than all at once. JS is just awful, though, because of the sprawling dep tree. I get why devs would prefer pinning as any one of the 1000 deps that get brought in could need an update and code changes on any given day. A sticky static version requires less daily maintenance.
- latentsea 2y ago
- sporkland 2y agoReminds me of the Rich Hickey talk Speculation[1]. There is a special place in hell reserved for programmers that break back compat (for non-security impacting reasons) with widely used libraries, including google's guava developers. Linus Torvalds seems to be the only engineer with his head on straight on this topic and he has to constantly dive in and berate people that are trying to violate it in his project. [1] https://www.youtube.com/watch?v=oyLBGkS5ICk https://www.youtube.com/watch?v=oyLBGkS5ICk
- throwaway2037 2y agoCan you provide an example where Google Guava broken backwards compatibility? I have used it for more than 10 years without any issues during upgrades. To be fair, it is a huge library, and I have probably barely used 20%.
- Freak_NL 2y agoOh, this is common. Fun when you have two different dependencies which both use Guava, but different versions, and you can't upgrade them to a common shared one. The solution there usually means having to shade Guava for one of them, which sucks, but it at least gets things working. It's not much of a problem when you use it yourself, but it is when your dependencies do.
- deleted 2y ago[deleted]
- int_19h 2y agoThe culture around JS seems to believe that, between semver and package version pinning, there's some kind of mandate to do things like massive incompatible API refactoring, so long as you update the major version number. The result is what TFA describes.
- ajayvk 2y agoI have been building a platform https://github.com/claceio/clace https://github.com/claceio/clace for teams to develop Hypermedia based internal tools. One of the main criteria for the technology stack and the feature set has been making sure apps can be maintained easily, after six months and after six years. Settled on using Go HTML templates, Starlark and HTMX. Go has a great track record of not breaking backward compatibility. Go templates are widely used by ops teams, any breaking changes there will cause ops teams to revolt. Starlark is somewhat widely used by build systems (like Bazel), any breaking changes there will cause build engineers to rise up in arms. The HTMX 1.9 to 2.0 upgrade was also painless, no changes required in my test apps. Only change required was to update the way the websocket extension is resolved.
- acdha 2y agoThe JS ecosystem definitely has a big problem from the culture developed in the IE6 era where people developed so many packages working around the limited language and runtime, but React does have part of the blame here: the way it’s designed forces everything into its proprietary model instead of web standards, so you end up with tons of components duplicating other projects but in React or providing shims for those projects, Facebook’s big devrel push prioritized getting started quickly on a proof of concept rather than maintaining a larger app so you had things like Create React App adding nearly 40k dependencies before you had written a single line of code, and the culture of focusing JavaScript over built-in browser functionality (which made some sense in the 2000s when you had users stuck with IE6) means that you’re going a lot of work in runtime JavaScript rather than the browsers’ heavily-optimized C++ – and it’s often hard to change that because it’s not a direct dependency but a nested chain. This is also why it’s slow and memory hungry: it’s not just the inherent inefficiency of the virtual DOM but also that having such a deep tree makes it hard to simplify - and since interoperability makes it cheaper to switch away, framework developers have conflicting incentives about making it easier.
- djbusby 2y ago> inherent inefficiency of the virtual DOM I was around when vDOM was being called optimized. I was also around when they called it DHTML. Get off my lawn!
- acdha 2y agoSame (I started writing JavaScript when it was called LiveScript in the Netscape betas), and I remember how the vDOM hype was conspicuously short on rigorous benchmarks – people would compare it to heavyweight frameworks which did things like touch elements repeatedly or do innerHtml cycles and say it was fast.
- rerdavies 2y agoI remember when all web pages were set in Times New Roman on a gray background. Unless you were browsing the web using a console application.
- emseetech 2y agoWe also have a generation of designers who "think in React" who don't approach the web like the web, but like a less form of mobile. A designer who has a solid understanding of hypermedia and puts its principles first would be worth their weight in gold to a team who wanted to move away from the React ecosystem.
- aktuel 2y agoThere is a good solution. It's actually a great solution: Write everything in plain JavaScript. You get a great language to develop in. All your problems will go away. No dependency hell. Excellent load times and performance. Superb compatibility.
- mablopoule 2y agoThis. In one of my previous job, the main product was 100% pure Javascript (using AngularJS), with a few (vendored) third-party scripts, and it was very nice to work on it. No package.json, no dependency issues, and above else, the workload we had was always related to business, and almost never related to external technical constraint such as a depreciated dependency.
- RUnconcerned 2y agoI... don't think that AngularJS + third-party scripts was what OP meant by plain Javascript.
- leosanchez 2y agoAnd I wouldn't say AngularJS v1 is nice to work with either
- mablopoule 2y agoIn general I would agree, but this project managed to avoid the main gotcha of AngularJS (the performance issues & the possibly messy data-flow), so it was holding out suprisingly strong, even pas the maintenance date of AngularJS. The lack of pre-processing steps, combined with good CSS and a well-formed DOM made it one of the rare project in my work history that didn't create any rewrite-envy. AngularJS or not, the main point is that avoiding piling layers of tooling that might force you to an upgrade for purely technical reasons was a nice experience.
- skinkestek 2y ago> You get a great language to develop in Every single footgun from PHP but wrapped in a nice syntax so people don't understand they are in danger. I'm deeply impressed by the Javascript community. What they have managed to create using a that language is amazing. But please people, do yourself and everyone who ever has to touch your code base a favor and use TypeScript.
- Cthulhu_ 2y agoThere's a few solutions that the community won't do for you though. Reduce your dependencies; the author proposes htmx, which is an extension of "just use the platform". For a lot of websites / applications, you don't need these tools; you don't even need a build step, because plain JS is fast and compact, browser support for most features is fine, and intermediates like CDNs or whatnot can handle the "last-mile" optimization of assets if needs be, with HTTP 2/3 being the other newer factor that makes asset optimization / a build step less necessary. Reduce your update frequency; a lot of the updates of these libraries are trivial, which is both good (fast updates and releases is good, many open source contributors are good) but leads to a high update frequency. But it's fine to run a month behind, the amount of actually critical issues are few and far between. If these projects have their semantic versioning correct, you should be able to see whether updating them once a month requires a lot of work. The fear, which is justified, is that waiting too long with updates means these compatibility problems add up. Especially when the ecosystem was still figuring itself out and did major backwards-incompatible rewrites (remember Angular 2?) this was a major issue, but it seems to have eased off a bit. Last big one I've run into was when eslint decided to change its config format, and given ESLint's old config could get pretty convoluted already (especially in a monorepo with partially shared configuration and many plugins), changing that was effectively rebuilding the configuration from scratch. Anyway. I frequently look to the Go ecosystem and attitude for things like this. And it's had an impact on the JS ecosystem too, it was only after Go came out and said "use gofmt, fuck your opinion on formatting and fuck spending time on trivial shit like that" did the JS and other ecosystems follow suit with e.g. Prettier and Biome. I unfondly remember peppering code reviews with dozens of "this single should be a double quote" and "there should be a newline there". Such a waste. Anyway, the Go ecosystem mindset is a healthy one. Go the language gets a lot of justified criticism and it's not for everyone / everything, but Go the mindset does a lot of things right or better, for less developer frustration, better future proofing, and more maintainable software.
- pjmlp 2y agoNow to make it even more fun, add something like Synk forcing updates due to security issues.
- deleted 2y ago[deleted]