Also, the design system matters a lot. Have a small team working on the UI components to tailor and extend the design system. Dont allow the rest of the teams to extend the ui components with new libraries. Stick with the design system as much as you can. The rest of the teams should minimize the amount of CSS they have to write to components placement.
Usually the datagrid is the soul of any enterprise application. Choose it wisely and be sure it covers as much functionality as you can and also that it is customizable on an "easy" way. There is always a team with the need of a datagrid that sorts, groups, filters the data with dynamically adjustable cells and multi header items without pagination. Welcome to hell.
Use one pattern: hooks, central store, whatever you want. If at some point you have to change it you have to know which teams are using which one. Dont allow team members of the same team follow different patterns. Code reviews must take care of this.
Hope this small tips help one or two teams out there. I have worked on the migration of 5 big enterprise applications from angularjs to react or from legacy desktop application to react or from server pages to react.
I made a lot of mistakes that costed a lot of dollars. I have tried to learn from them. Also, dont take me very seriously, I am pretty sure I am about to discover another mistake I have made.
You are just stating the problem the article complains about.
Whose opinions are those? You need to take a lot of decisions.
Moreover, those decisions which seemed good (to you...or the one that dictates those strong opinions) at the time you took it, are not valid just months or years down the road. So you will need to reevaluate them periodically.
Moreover, even if you are happy with your decisions, you might be forced to take them again, because the library went out of fashion, unmaintained, or the developers just stop responding to issues and ignore you completely. This is already happening to a project I work with where the react-router developers just went to build their own nextjs competitor and stopped responding to issues. Same with styled-jsx from the same next.js team, not even themselves seem to be using it anymore.
This never happened to me using Rails. True some gem might go away, but at least it usually is some helper thing and not the core of my f*ng application. Same experience with django and many other uncool stacks.
So, yes. React is amazing if you are facebook, google, amazon, building a side project or just working for your own resume. It is not good for the average business. It is not good for enterprise applications.
In my own experience, at least.
the person who has the authority to call the shots and leads the project.
The error is right there in the article:
"After nine months, we have more than 50 pages created. The developers notice that function components are as good as class components and start using them. So, now the project no longer follows the original coding guidelines. It’s more like a personal choice for each developer. And for me, that is OK."
This is where the screw up happens. This is not okay, and as the person responsible for the architecture the author should have made a clear and concise decision and then get everyone to comply with it. You cannot let your developers run wild and then complain a year later when everything is a jumbled mess. Even more opinionated frameworks won't save you because the application is so large it likely would have happened regardless.
Making those sorts of decisions is supposed to be what the architect does. It sounds like the author did not do so.
Note that your suggestions do not address the main problems: time spent upgrading libraries, brittle dependencies, and linear degradation of performance and stability. Code standards and code reviews cannot help when the problems come with the standards.
There's certainly a case to be made about large teams being a problem of their own, but FWIW, a lot of projects _don't_ have large frontend teams (I'd say 1 to 3 frontend devs is fairly typical). Standardization _across_ teams can definitely be a problem, but at some point one has to wonder if it isn't more sensible to just have each teams develop separate apps that load in separate pages, or, you know, just use a more batteries-included, prescriptive framework.
i now have this aliased to `ni`, so i get to say `ni` to the app often.
When you have a big project, you have to keep a consistent architecture. You need to keep using the same tools and patterns so that you have cohesion in your code base.
The worst thing about new architects on long lived projects is you typically get 2-4 ways of doing the same thing. If you're going to do that it needs to be so good that you don't mix and match.
If you are going to mix and match, you need to have a solid approach to splitting your dependencies, one way I'd have looked at doing this is by splitting this into multiple sub SPA applications and each mini project would be able to conform to it's own standard as long as it could interface with the glue application, this is by no means foolproof, but it gets you a lot closer to a maintainable situation from my experience.
Why I like this approach is that I saw a comment from someone saying they'd hate to be on a team with a uniform style. I completely get that, innovation is super important, but you have to build boundary layers between the different styles so you don't end up building such a hodgepodge of dependencies that you can't get things to work anymore. It also keeps your build times down and reduces time to get started working on your module.
Again same comment you made, I've made mistakes, trying to learn from them, maybe my current approach is bad too and there's a better way.
Use a monorepo with many `package.json` files. Then someone working on a data grid component for example can add the packages they need for that component and no one else's code will depend on it and it won't break anyone else's.
To be honest, there isn't a lot the author is wrong about. Sure, having a .NET team adapting to React is harder but nothing seemed egregious in the way they tackled things. The point about React including so little that you become reliant on a ton of external dependencies that see even more churn than the usual JS framework landscape is a very valid pain point, especially when you are building a very large application for the long-term. Granted, a lot of that criticism holds true for the entire JS scene where the churn is simply ridiculous and you have to cross all your appendages and hope for the best before you try to build a year old project. But React is especially problematic in that regard only because there are so few batteries included (which is great for small/mid sized projects, but the opposite if you are looking for stability).
Ultimately though, I just shudder to think about writing large, complex, enterprise Apps in the latest and greatest JS/front-end frameworks due to the crazy levels of churn in frameworks, libraries and APIs. React now looks completely different from React from 1-2 years ago. Libraries fall in and out of favor. Some keep up with the ever changing API of the parent frameworks, others die off. It's like an entire ecosystem that has ADHD and as someone who has built several small to mid-size React and React + Electron apps in the past, that ultimately turned me off the entire endeavor (I'm an ML Engineer, but I love software engineering and building stuff for fun). I would much rather take "boring", stable languages and frameworks and spend my time honing skills that actually matter and help me as a software engineer throughout my career, rather than spend a week trying to get webpack figured out, till the next big webpack update when I'd start over from scratch again.
It's a feature, not a bug. Not understanding this is a red flag that you're going to run into problems.
> React now looks completely different from React from 1-2 years ago.
Does it? I've worked in React, at enterprise levels, for close to 3 years now. Except for the addition of hooks, there hasn't been a whole lot of churn. React today is still the react of yesteryear, but with extras.
Imo the biggest failure of the author was to jump headfirst into a stack they weren't familiar with it, and then blame it on the stack.
I know it's en vogue to hate npm/react/js "because the ecosystem", but at this point, picking the ecosystem and then blaming it is a self inflicted wound that I don't really have patience for.
> It's a feature, not a bug.
Yes, a small, light-weight framework can be a good thing. No one called it a bug. But like everything in life, there are trade-offs involved. And I'm not entirely convinced that it is a good tradeoff in the crazy JS ecosystem where everything is changing and breaking all the time, especially if you are building more complex things and don't have an army of web-devs to keep the house of cards from falling down.
This attitude smells of "you're attacking my way of doing things, therefore you're wrong". While there's truth in both your claims and the GP's, there _is_ churn and there _is_ a ton of garbage in the ecosystem, that much is very true.
The nuance is that the distribution is not uniform: lodash has been stable for ages, axios is perfectly fine for HTTP requests, etc. Where it gets sketchy is when you get to the fringes of what a framework is expected to do. But at that point, not even Angular or Ember can save you.
As for framework-specific churn, React itself is not the only cog in the equation. As part of my job, I see a lot of React codebases from various periods in time and honestly, yes, there's a lot of churn. Looking only at React's API churn, we have code using hooks, class components, HOCs, render props, heck even React.createClass.
And then there's hipster libraries that willy-nilly break APIs to match each new React idiom, libraries that just can't make their minds about what their API looks like, abandoned libraries that uses the old Context API, libraries that depend on componentWillUpdate, libraries that read the shape of the virtual dom node, libraries that depend on those libraries, and on and on goes the rabbit hole. React Router, for example, is both extremely popular and notorious for having given people migration headaches.
On top of that, there is of course the self-inflicted pain: redux-saga messes that no one wants to go near, misguided attempts at "functional programming" and other forms of over-engineering, etc.
But here's the rub: Angular _has_ idioms for forms. You don't wrangle w/ random breaking changes in react-form there. Angular has a router. No need to worry if your favorite router lib will break APIs when Suspense comes along. Angular has HTTP requesting. No bikeshedding over axios vs isomorphic-fetch or whatever. Angular has state management idioms; no fussing over where async stuff goes in redux (assuming you're not still arguing redux vs mobx). Pluralization? Hope what you picked is maintained. CSP support? Yeah, go google that, I can wait. Etc.
You can definitely become a competent React dev and spend many years on good, well maintained projects in React-land, but that doesn't mean there aren't problems directly attributable to the React's limited scope as far as "frameworks" go.
I'm not that familiar with React (although I have had the misfortune of working with Angular), but I've seen the horrific Spring "framework" defended that way: it doesn't actually include any functionality because it's designed to be open ended! What it turns out to be is the most useless thing that ever happened to programming: it's pure overhead, undocumented (surprising) behavior, unwanted defaults that you have to spend time working around without the benefit of actually simplifying anything. Not saying React is the same (like I said, haven't really spent much time looking at it), but it's adherents defend it the same way Spring's adherents defend it.
I have been using it since you could only track state in class components, and I personally think it looks drastically different with the evolution of hooks. I interpret components differently than before. The patterns for doing most things has changed, such as the inherent deprecation of the higher order component and render props pattern. I'm not implying that it's bad there have been changes (some are absolutely warranted), but rather explaining how I do believe the library looks different than it did before hooks.
>I know it's en vogue to hate npm/react/js "because the ecosystem", but at this point, picking the ecosystem and then blaming it is a self inflicted wound that I don't really have patience for.
I work in corporate, you wouldn't believe the infantilism in frontend development, always doing everything but modeling the problem and iterating that model. People are also not good at picking up on cohesive properties of libraries. But this is life in the name of holy velocity.
So you are a beginner.
Is that true? Can you give me an example of what you're thinking of? I've used React since pretty much the beginning and the only "completely different" looks I can recall is class-based components -> functional components + hooks. And even that evolution was pretty comfortable and backwards-compatible.
If I was a full-time web-developer, I'd maybe be willing to live with the churn of the JS ecosystem, but as someone who enjoys software engineering and building fun projects, the churn is simply exhausting and a big turn-off. I spent a year doing a lot of intensive React + Electron + D3 + MobX and all the associated stuff (webpack, npm, node, etc) in 2018, and then at some point I realized its like being on a hamster wheel and you gotta keep going frantically just to stay up to date with the newest libs and toys and APIs and current group think. Meanwhile, a year spent just writing and learning good software in Python (for example), gains me so much more transferable skills to anything I touch as a software engineer in the future.
I still like the power of being able to make user-interfaces easily and there are plenty of things I enjoyed about developing web/electron-apps, but ultimately I was just turned off by how much continuing investment of your time it requires just to stay relevant in the field without imho adding any real value to actual software engineering skills.
> React [includes] so little that you become reliant on a ton of external dependencies
React, since hooks, includes a full state management solution - Context, Provider, and hooks.
Second, even if you want an actual state management library, both mobx and Redux are quite stable. Applications I have built in 2016 are still running and building with no pain points today, except maybe that the tooling is way better now.
Third, all this noise about "the JS scene has so much churn" is kind of crazy. I don't know what kind of library evaluation techniques everyone else has, but React is backwards compatible with techniques they've been saying they'll deprecate for years, version pinning works perfectly fine, and with TypeScript there's less and less churn and mystery than ever before.
> Ultimately though, I just shudder to think about writing large, complex enterprise Apps in the latest and greatest
This is a comical take. Facebook is powered by React. Large, complex, enterprise, and fully powered by the cutting edge of JS frameworks.
> React now looks completely different from React 1-2 years ago
But still fully supports the previous way of working, meaning not only has none of your knowledge been invalidated, but you have additional tools at your disposal.
> Libraries fall in and out of favor
react-router-dom has been my goto for quite some time, as has mobx. Again, you can version pin and stick with any solution as long as you want to - my things powered by react-router 3 are fine still.
> I would much rather take "boring", stable languages and frameworks
> I'm an ML Engineer
Is it not true the entire ML ecosystem has been reinvented in the last 5 years? My React code still builds & runs from 2016. I really feel like this is a case of "external person overestimates complexity in external domain, underestimates complexity in internal domain" because everything you're saying sounds like you dipped your toes, and didn't actually build applications.
Final thoughts: you don't need to update Webpack to resume building your old project. Your build scripts work just fine. Better yet, don't eject from Create-React-App or some other build provider and you never even need to think about this stuff. React is boring and stable, speaking as someone who has used it for half a decade and sees no reason why that won't just become a full decade.
"Facebook is powered by React. Large, complex, enterprise, and fully powered by the cutting edge of JS frameworks"
A very bad example. Most software of significant cost and size is serving a industry, and not the industry itself.
Facebook can break things. If your insurance company or bank break things... Get my point?
Fifteen years, maybe, but because of new technology. Actual physical machines that did not exist earlier.
The churn in JS frame works is because because because, no better reason.
Which is the biggest foot gun I've seen in my life.
There is a surprisingly high number of developer that still don't get it and will make those beautiful applications where, thanks to a naive usage of this, will create applications that rerender the entire application on every keystroke.
Sure, but that hasn't been around even 2 years. Prior to that, there was a different approach and philosophy to doing things. I remember when higher order components were all the rage till suddenly they weren't.
I'm not advocating for stagnation, but at the same time, everything in JS land feels experimental, even in established frameworks, and the entire community keeps marching along as things keep changing. Which if you are a full-time developer doing that, is fine I guess, but it is not the norm compared to pretty much any other software engineering field.
> Second, even if you want an actual state management library, both mobx and Redux are quite stable
I cannot say enough nice things about MobX (although I was using it back when it didn't use Proxies so you had to deal with a lot of cloning back to native JS objects which got a bit ugly at times), and I don't disagree with you on this point for state management, although I personally could not stand redux despite 90% of the community vehemently singing its praise.
> This is a comical take. Facebook is powered by React. Large, complex, enterprise, and fully powered by the cutting edge of JS frameworks.
I should have perhaps qualified that better. Yes, I know there are people writing complex apps, but I was viewing it from the POV of a non FAANG type place with tons of engineers to throw at a problem. If I was a single person or a very small team trying to develop something complex, I would place a much higher emphasis on a more stable development environment/language/framework.
> Is it not true the entire ML ecosystem has been reinvented in the last 5 years? My React code still builds & runs from 2016. I really feel like this is a case of "external person overestimates complexity in external domain, underestimates complexity in internal domain" because everything you're saying sounds like you dipped your toes, and didn't actually build applications.
Let's take Pytorch as a comparison framework. It's had tons of releases, but at a fundamental level, the core API has stayed the same. I've ported 3 year old code to the latest version with pretty much negligible effort. And at its heart, it is because APIs are kept very stable and people aren't deciding each year that they need an entirely new way of doing ML or performing automatic gradient estimations, etc.
Similarly with Python... there have been a bunch of Python 3 releases in the past few years but they each add new things that are useful without making big changes that suddenly change how everyone would tackle building a new piece of software.
On the other hand, porting a 2+ year old React app to the latest version of React (along with bringing dependencies along) would be a very painful process. I know this, because we've done this at the company I work at.
There is also this implicit assumption in JS/React land that you are going to come marching along with all the latest changes. Heck, less than 2 years back, their documentation site wouldn't even let you view older versions of React documentation, so the moment they released a new version of React, the docs would only ever show you the new docs. What's funny, is that today they supposedly have links to their older docs...but every fucking link is broken :-/
example: https://reactjs.org/version/16.8
And nobody probably even knows that, because there is a general expectation in the field that everyone just keeps staying up to date with the latest and greatest and deals with whatever pain points come along with that and no one has probably even tried to access older documentations or raise issues about it. Which is fine, like I've said many times before if you've made your peace with it and that is your full-time job, but it is not the expectation or norm in most other fields.
Finally, I should state for the record (because you stated otherwise in another reply to me), that I actually love javascript...well at least ES6+ JS. I greatly enjoy(ed) JS, JSX, developing in VsCode, and even building things with React, Mobx, etc. I'm not a software engineering snob who looks down on JS and the ecosystem. But I also have a more diverse viewpoint because I work at a small company and get to wear many hats and have been able to do lots of different things (ML Engineer, Front-end work, write and deploy pretty complex software, etc.). And while I have a lot of fun doing front-end stuff, It still feels like there is a lot of constant overhead to it, and that is pretty unique to this one field compared to most everything else.
I would argue that you don't need a heavy framework to make maintainable JavaScript application. For large enterprise applications that must last a decade or more you want to use standards (such as Web Components) implemented by the web browser itself instead of third-party libs such as React.
Like parcel snowpack works great when you can use it. Hoping it catches on because I really loved how fast it was.
One could substitute React with almost anything js-related, and the post would still incite flame.
I, for one, am glad to see the push back against the mad craziness that has dominated the Node.js/Framework word.
It is easier to speak than listen, easier to write than read, and easier to build than test... Hence Node.js, and JS Frameworks.
I do love programming in Javascript, have not done it for a while, as I cannot abide the ignorance and arrogance that goes with the ecosystem.
I love plain old vanilla JS....
I worked at large accounting software provider, and internal billing system used static pricing which was changed once a year. The company wanted to move to a more flexible system where pricing can be setup based on few rules like customer type. For this the ui and backend system needed to be developed. Design I proposed was a single "monolithic" service which did everything including UI and UI was supposed to be a old style mustache templates and some minor jquery. Instead they went with pub-sub systems, 4 different microservices, a react based UI, api which used json-schema, even to send data back to UI. When I left a team of 6-7 people was working full time on this and they were about 20% done.
Devs like to have fun, learn new things, play with complicated things - that's all it is. It counteracts the dull features that most developers have to ship.
What could've been an effort to split the existing service into manageable smaller services and rewrite components as needed turned into a multi-year ground-up effort. When I left they were no where near production ready, with significant technical debt and code rot from already years out of date libraries and practices.
It went swimmingly right up until QA was more or less told not to file any issues found, and then those issues were used as a reason we needed to use a TypeScript and Material-UI app he wrote over a weekend and said was "almost done." The bugs in question turned out to be minor visual bugs, and like I said, none of them were filed or even mentioned until this replacement got dropped in our lap. In fact, no problems of any kind were reported until this moment.
Instead it took another 6-8 months to get to feature parity with the app we'd already developed and now thrown away (or feature "parody" as my boss put it), it was full of bugs, development is slow and pretty directionless, my boss gets bored and contributes code that runs in the O(n^12) range (yes, really) before languishing in a draft PR for months and then getting dumped on us to actually implement for real, and it's been a year and a half with no end even remotely in sight.
I really want to find somewhere else but that doesn't seem like a realistic goal right now. Not to mention my enjoyment of programming died years ago and I haven't written code for fun in as long as I care to remember.
If you're building a new internal webapp from scratch for a small internal use-case, you just end up with a hundred different poorly-maintained apps.
But in the situation where you're adding a page to an internal app, it's trivial to make that new page a SPA React app, since the framework is already there waiting for a new component.
What should have happened ideally is that the blog post author would have said to the CTO:
- we're going with React
- you've chosen us to guide you in this
- you now need to trust that my advice on standards and approach is correct
- you need to get your developers to do it the way I say
- if you don't, then we will be building a frankenstein React project which is built like a .NET application
- the success of the project is at risk
And the CTO would have been wise enough to agree and pull his people into line and give the blog post author the authority to demand things be done as he says they should be done.
But that's politics and hard to do.
Its impossible in JS to not have made bad choices that didn't last or cost huge amounts of dev time to workaround.
The real key to politics is building up enough political capital to be able to survive when things go south. If you continuously make bad decisions you will inevitably be fired. Even if you were always learning from them each time.
I would say:
- communication - here is why and how we made these decisions and the assumptions we followed. if they turn out to be bad choices, here is where our assumptions were wrong. we are going to learn from them in the future.
- management buy-in - you need the CTO to buy into your decisions and reasons and not just to trust you to make them. let them make the decision. avoids the blame game in the future.
- avoid shiny things - you have to stick with what you chose and focus on delivering business value rather than always thinking about that re-write or the new shiny thing. work is going to be less fun and you will feel like saying "a rewrite to this library is going to make us more productive" but it rarely will and unless you have a strong CTO its always going to be hard to justify.
I remember one in particular that would push incredibly tight deadlines for huge features, got frustrated at the pace and hired another dev team, and didn't change the way they set deadlines. This of course fixed nothing. Then the other team they hired pushed a huge change to the repo, almost every file in the codebase was touched. Nearly 70% of which was whitespace changes and the other 30% was unfinished code that did not compile. We later found evidence that they hadn't even run the code before pushing the changes. The client demanded that we merge it, were told it would break the build, got mad when we merged it and the build broke, then tried to use that (and a whole bunch of almost hilarious and similarly-effective arguments) against us in a lawsuit which they lost, and then lost the countersuit.
So yeah, that was a fun time for my liver, to say the least. Especially since the C-levels decided to focus the entire company's output on that lawsuit while the engineering team sat around mostly twiddling their thumbs.
You have a team of developers that have a collective experience of perhaps eighty years in your organisation.
Do as I say, me who just popped in and afterwards will pop out again....
That is how millions and millions of dollars are lost in this business.
That's where his 3 weeks of decisions about libraries reveals a real mismatch between React and the enterprise way of doing things. React requires a lot of decision making, and enterprises are bad at making decisions.
Ultimately, the fault is with the enterprise. Sometimes you don't need official data, you just need someone with good taste to make a decision (and if your developers cannot usually "disagree and commit", that's a people problem). Save the data for the big picture stuff.
That is probably what I hate the most of front-end development compared with back-end or Mobile. There are too many options, and that certainly does not promote consistency within the project.
As a React dev since 2015, things were pretty bad initially in this way - but now you can literally build complete applications with React, react-router-dom (clearly the winner in this regard), and your choice of state management (mobx 6 is, to me, the best). Redux is king and MobX is the slightly more adventurous challenger.
I have built an absolute plethora of applications and I do not have any external dependencies beyond those two, TypeScript, D3, and the occasional helper library (date formatting, deep-equals, etc).
Speaking to some other points as well, the React core is not really minimal at all anymore, since the advent of hooks you can actually completely bypass external state management and just use hooks and your own context. I've done this on a couple smaller applications lately and the hooks `useState` and `useEffect` are actually insanely powerful.
Last but not least, React has insanely strong error messages and linting warnings. Things like non-unique key errors, debug symbols knowing the actual source of errors, stack traces enumerating thru the actual React tree so you can see your error, dependency array validation for useEffect, and more that I can't recall at the moment - it's the top library for UI for a lot of reasons and I think your opinion sounds a few years old.
I think its still quite bad for debugging. I get a lot of "look here" for errors, but there are still times I set breakpoints on the internals to try and figure out what is going on. Usually in combination with some babel plugin messing things up, or some webpack caching issue, etc. I still think more could be done here, but adding the necessary debugging stuff would bloat the core.
> Redux is king
Redux is quickly going out of fashion. Interested to hear your thoughts on how long you think it will remain around though or evolve. When I look at redux-saga/redux-observable projects, its incredibly verbose for such simple things. And there seem like very simple solutions on the horizon with suspense resource fetching stuff.
Eg, here’s one example clip: https://youtu.be/yodWEPgn8NA
The first is mistaking your level of desire for something to happen with the actual probability of it happening. It's clear he doesn't just think web programming is going to collapse, he wants it to happen. And it's distorted his estimation of its likelihood. I'm sure in 2030 he'll be making videos confidently predicting the collapse of web programming by 2040.
The second is where an expert in one domain considers its complexity to be inherent and unavoidable, while assuming other domains, of which they are ignorant, are inherently simple. Then when they try to engage with those domains, they run into significant complexity and experience the uncomfortable and unfamiliar sensation of being an amateur again. Since the unfamiliar domain is, by their estimation, simple, they conclude that the complexity they've encountered is unnecessary — a result of people working in that domain being too stupid or inventing busywork.
The third is the mistaken belief that our means will improve, but that our desires will remain the same. So, right now we have certain requirements, and in order to meet them requires us to do a lot of complicated, cutting edge stuff. But soon all that complexity will get figured out, the cowpaths will get paved etc., and we'll happily just pushing a single button to do everything we need. The reality is, of course, that our requirements will just get more complicated as well. Human civilisation has been on this treadmill since time immemorial.
Like the data science guy I worked with who complained we were making authentication and access control complicated.
The argument basically comes down to whether web development is or isn’t slower than it should be, and whether it will become dramatically faster to do in the future
> What most web developers spend their time doing is useless busy work that is not actually objectively necessary in order to create the functionality. It's just dealing with a bunch of weird conventions by some other software that they are trying to use that are there because some other other weird conventions by some other software that they are trying to use. If you just strip all that crap out, you can be tremendously more efficient.
Not only is this a very arrogant sentiment, but his reduction of all web development down to manipulating "weird conventions" doesn't fit with my experience. I don't sit around all day messing around with Webpack configurations or leaning new frameworks. I deliver software that addresses business needs, that happens to be accessed via a web browser.
He also says that jobs with the title "frontend", "backend" and "fullstack" for the web are not safe jobs. Many game developers, operating system designers, and large desktop applications will also have "frontend" and "backend" separations of responsibility as well, because they often involve different skill sets or knowledge.
I actually agree, but maybe not for the same reasons he gives. The problem with modern tech stacks is that, yes, they're insanely complex, and each of the dozen or so individual components has dozens if not hundreds of its own hidden expectations about what should be where and what it should look like. As long as you meet all of those expectations, everything works magically like it should, but as soon as you miss one, you'll be lucky if you even get an error message that you can google the solution for.
There are two efficient ways to solve this: 1) no dependencies, build everything from first principles that you already understand. Then, although there will be plenty of assumptions baked into the code, you'll know what they are and how to deal with them because you put them there. 2) take advantage of pre-built solutions, but actually read and understand the docs before you rely on them.
The second solution depends on two rarely present preconditions: one, the docs actually exist. Two, management understands that it takes more than twenty minutes to realistically absorb 500 pages of dense technical documentation.
What we end up doing as a workaround is using the off-the-shelf stuff without really understanding what it's doing (or are you telling me that you understand the 9000 files that are installed by NPM? I'm not exaggerating, BTW, go take a peek). We cross our fingers and hope that we got all the assumptions right, cut-and-paste solutions from stackoverflow, and let the horrifically inefficient solution take the place of actual engineering because the "timelines are aggressive".
There is a reaction against this happening right now. You can see it in hotwire from 37signals, Alpine.js and my own response to it: https://htmx.org
“Simplicity is prerequisite for reliability”
But yes, I prefer the microframework approach.
I chose it because of the skillset that our current (small) team has. There's no way our 'designer' (more an HTML/CSS guy) could have wrapped his head around JSX, the way it mixes scripts with layout markup.
The way Angular separates concerns for us is great. And the components are extremely flexible and reactive and useful for iteration. And lazy-loaded routings? Yes please.
And with the Angular CLI and TypeScript typings and using VSCode it's an absolute joy to build sites with.
[1] https://nx.dev/latest/angular/core-concepts/computation-cach...
But the recent versions (and updating is also a breeze - mostly) should be faster. And particularly if you drop support for ES5 browsers.
All the React routers I know of support lazy-loading well.
I'd argue far better than Angular handles it. React components tree shake extremely well out of the box and I've rarely had to worry about bundle size when lazy-loading in React. Whereas Angular's dependency injection framework and its "modules", in addition to being irritating busy work as soon as you realize you can't trust the CLI's scaffolding, do nothing but get in the way of proper tree-shaking and good webpack chunks/bundles.
With a small and dynamic team that loves functional programming and reactive state management, React is great. But in larger enterprise projects with many experienced Java/.NET devs, Angular just seems to be the better choice to me.
None of the code you write is ever really touched by a browser anymore. At the very least it's minified.
I write all my components like this:
const props = {foo: 1, bar: 1}
<MyComponent {...props}>
{children()}
</MyComponent>
function children() { return foos.map(b => <div>{b}</div>) }
Why do I have to use a weird language with non-standard JS stuff. Writing conditionals in JSX is horrible, and props are unnecessarily verbose when we have ES6 language features like structuring.It could easily be just a nested tree structure.
> React’s team enjoy experimenting with new ideas, but this is killing the ecosystem! They should be brave and take the blame for it!
Have to make a lot of assumptions with this sort of thing, but I can't imagine that attitude results in high quality engineering work.
https://reactjs.org/blog/2015/02/24/streamlining-react-eleme...
Projection if I've ever seen it.
Personally, I think if you want a deep understanding of React you need to first get in a few cycles of working with DOM, JS, CSS, etc. directly. Maybe throw in a functional programming language too. Then try to pick up React.
Given this kind of team and leadership, why does that still make React the best choice for them?
Maybe the team is a bunch of n00bs, so what? Wouldn't the perfect framework/language make it hard[er] to screw things up regardless of the lack of dev skill? For a big multi-year project it often strikes me that the best tools are those which are old, boring, and unlikely to change.
That being said, huge-multi-year development in _any_ js framework seems terrifying to me because of the churn in the general js/browser environment.
Also: I think the author doesn't cover this a lot, but it sounds like they REALLY saved their bacon by doing the boring due-diligence of carefully documenting the decision process behind all the choices they made. They probably would have had slowdowns and surprises and roadblocks no matter what, but someone's still got a job because they took time to get it in writing.
— Peopleware (1987) by Tom DeMarco & Timothy Lister
Most enterprise teams are poorly skilled with bad leadership. Modern frameworks and coding paradigms are a bad fit.
No it wouldn't, not for an enterprise application that is supposed to last a decade or more. Instead you want to use standards such as Web Components that will last essentially forever.
For a developer just looking to make the thing their design team sent them as quickly as possible, this makes good sense to me. And I get that project/file structures can be wildly jarring to an uninitiated dev - I remember looking through a Java repo for the first time :shudders:
But! Isn’t there a necessary step of understanding why decisions were made the way they were? In my experience as a front-end eng, even if a previous project involves other-worldly dependencies or FS compared to the one I’m on now, if I understand the trade-offs of the approaches for the previous project, no amount of knowledge is untransferable.
Yeah, unless you have a sufficient base of React (or at least JS) devs to shepherd this, this is obviously going to be a problem for choosing anything that isn't .NET, and the further from their existing .NET experience it is, the worse it will be.
.NET is a workable web app platform, even for isomorphic apps via Blazor. If immediate onboarding of .NET devs was a key requirement, .NET was the obvious answer.
I’m on a team that has (I feel) been relatively productive with SPAs backed by serverless microservices in an enterprise environment, but its largely greenfield. And, frankly, at this point, the major SPA frameworks are really “boring stuff that works”.
Roadblock #1: I am not even sure why does it matter what is behind the curtain, only important thing are REST contracts, everything else is splitting team front-end / back-end. Everyone can have what ever naming convention they want. If project is enterprises it means that has more than 11 people or what is considered as a high number of SCRUM team, so spiting concerns is important and necessary. Everyone does it all (all full-stack devs) just does not work.
Roadblock # 2: This is due to experience, and it is up to UI team lead to decide, rest they follow. Sorry, in enterprise projects democracy does not work, maybe in the first few meeting but there you need to draw a line. Regarding dependencies, this is strictly role of one person, everyone else works on 'git pull' forbid everyone else to fiddle with package.json use lock file strictly and package versions, and you will not have any issues, each machine will have exact copies.
Roadblock # 3: This is not a blocker and Hooks have solution for any kind of pattern, it is still possible to use Redux pattern without issue.
Roadblock # 4: Machines can get slower, and in my team we had similar issues, but hey you cannot expect to work with 2GB in 2020, not realistic especially with Chrome sucking memory with 34 tabs open. Don't forget VS Code is built based on Chromium so basically you have two vampires on you computer. And having virtualized environment is even worse.
Roadblock #5: Saga in my case was relief, if you structure correctly Redux Actions and Reducers in neat way, and if you split your concerns, you do not have any issue, in fact it was working as a charm.
Again there are multiple approaches how to deal with this, even split project in multiple smaller SPAs if necessary, but at any point not issue with React but more case of PEBMAC :/sorry.
> I will not encourage using it for enterprise applications.
Almost like large-scale projects have different requirements and the tools generally used on large scale projects (like .Net) have adapted to reflect those requirements.
First - GRRR. What defined this as an "enterprise" app? Facebook is an enterprise app, dude, with millions of transactions a day. Just because an app is big doesn't make it an "enterprise" app.
architect was hired from outside to create a proposal for a team that had no one capable of operating in that role (and apparently the CTO as well)
"He already has a development partner in India, but they lack experience in building web applications." - this is a massive red flag
architect was sent away to do proposals without anyone talking to the development team to get any buy-in
architect got the background of the dev team from the CTO but neither architect or CTO talked to the development team (who would be implementing) prior to doing a proposal
"the technical lead ambushes me" - this is the first time the tech lead and the "architect" interacted. There's no "ambush" here; it's a failing on the CTO+architect's part to communicate to the team in advance, and perhaps at least involve the team lead
CTO is against angular but his outsourced team is familiar with .NET and Java; why is there even a need for an "outside architect" to make this choice when it's only between React and Angular?
"the CTO is backing his team, which is normal. He had known me for just two months, while he had been working with his team for many years." - Why is no one on the CTO's team, after many years, capable of investigating and making these decisions? Why did they need to go outside? If the plan was to continue using this outsourced team, why didn't anyone invest in their training to be self-sufficient vs a direction from on high? Why was there zero training plan?
"And that’s how we end up with three ways of doing things. There is no consistency anymore." Where is the CTO during all of this?
Enterprise apps tend to have much lower volume of users but a ridiculously long checklist of features.
what I find, with virtually every "new technology" that's come out in the past 20 years is that the "way of doing things" is not only completely undocumented, but also not agreed on by any two people. I can't remember the last time I found technical documentation that even bothered to describe what problem the technology was actually designed to solve in the first place - or was even written by somebody who seemed to understand why that would be important.
You can't expect an application to remain easy to develop when people do not adhere to your development protocols.
As for the (build-time) performance concerns, I think there's some work here. They have a _big app_. And if you're compiling a 220 page app in a single build, it's going to get slow. You'd have the same problem, though, with a native mobile app or a very large C++ app: at some point, you need folks focusing on the infrastructure bits part time. With a relatively small number of changes, they can probably make some big wins: adding build caching for local development, using an NPM proxy (to avoid downloading 600MB of deps over the public internet on every build), looking at alternative hot reload plugins, etc.
That's not to say React is without problems, but I think it's worth considering that _almost any_ technology of the scale of React is going to have drawbacks, especially if you don't have someone in-house who has really significant experience making it work well. Companies like Airbnb, Facebook, Uber, etc. all have whole teams ("JS Infra") dedicated to this stuff, in the same way there are teams like Ruby Infra, etc.
The big pain point of Redux (IMO) is that you do you data fetching separately from managing the data in your data store. It means that you need to add this glue layer between the data that comes back from your API and the redux store—you need to re-model everything. Every time you get new data, you need to go out of your way to remember to update everything that could be affected by that data.
GraphQL (I'm fond of Apollo) gets this more right. You can still use REST APIs with GQL (usually not by default, but it's possible). What this means is that you model your data in the way that the API expresses it. Your back-end folks aren't going to be lost when they read your code, because it matches the shape of the data they're already familiar with. The client-side cache means you don't need to manually fiddle with your store to invalidate stale data (I've yet to need to manually reach into the cache to perform updates).
That's not to say GQL is without its own issues. It is yet-another-thing, but it's one example of a solution which doesn't get quite as hairy when you've got 200+ pages in your app.
I don't have any recommendations for pure client side applications though, but for those you can probably get away with using contexts and hooks for quite a lot of the state management.
I am struck that a lot of us here start the comments with "I have been a React developer for [3, 4, 5] years"
I think this illustrates the fundamental weakness in the approach of people in the Javascrpt Frameworks world.
Billion dollar organisations build software that will cost tens of millions to develop want, or should want, more experience than that.
Javascrpit, and "Web 2.0", generally have been around long enough to meet the requirements, but this churn in frameworks is enough to make anybody with a stake in organisations shake with fear.
IMO plain old vanilla JS with a sprinkling of libraries for syntactic sugar (and they can be hand rolled - or use JQuery) is a much better proposition than all of these shiny and new stacks that keep getting deprecated.
Web front ends are a huge boon, and the settling of basic JS syntax and implementations makes some very good things possible that were not possible twenty years ago. But the whole industry is being held back by allways wanting "better", and not accepting "good".
They are huge productivity boosters. I agree that they are often used irresponsibly resulting in poor quality software. Poor software isn't limited to the browser, however. A lot of commercial software is garbage. Profit incentives seem to encourage software that is barely fit for purpose.
I have no idea what the figure is now, and now I have more experience, seen abject failure defined as tremendous success I would not be surprised if it si worse in fact and better in annual reports.
1. Why hire a team of non-webdevs to do webdev. (on 2nd read, it appears they wanted to use the same team from the WPF app... ¯\_(ツ)_/¯)
2. If you build and treat React components and their APIs as the abstraction layer, then they're just components... who cares how they're implemented.
3. Just because the existing project is big, doesn't mean your new one has to be... split it up!
4. Redux... the root "technical problem"
My hot take is that the authors technical issues probably come from Redux and not React. Using redux as the core of your application is like pouring glue on a lego set. In an ideal world this is great because everything is strong and well defined. In reality, it prevents flexibility and applies hard constraints to the entire system.
That one choice of using redux effects the decisions you make in every component. You lose flexibility to encapsulate features and experiments. You're forced to bend over backwards to do things in specific ways.
Redux is the JS equivalent of the Windows Registry.
Love it.
I find Dan Abramov a great guy, but it was he who brought us Redux and rose to such fame because of it, and its now considered a bad way of doing things (or maybe just a ridiculously verbose api) and caused a huge amount of pain for a lot of people (I am not blaming him tho!)
Now we have hooks as a collaborative effort involving the same guy, but they feel hacky in a way, and almost like they will not last either.
It really feels like this reinvention for the sake of reinvention. I can easily imagine the API I would like for managing my data layer, but its seems like we are trying to shoe-horn something into the React way when maybe it isn't the right fit and we need something else.
However I could totally imagine that a team which is familiar with advanced patterns for "connecting everything together" are unhappy with the bare minimum Redux approach. MVVM can be pleasant to work with, and isn't necessarily as much of a ceremony and chore as the redux stuff.
Angular 2 (or whatever version number it is now on) might indeed have made them happier.
This is Nir Kaufman's code. I think this makes Redux far more usable, it removes the need for thunks/saga etc.
Here is the talk: https://www.youtube.com/watch?v=JUuic7mEs-s
Here’s how we avoided some of his pitfalls:
* Small team of talented developers who didn’t always agree on libraries and methodology, but worked through disagreements to reach a consensus
* Recognizing that libraries would change over a two year project, and being ready for major library migration and refactoring
* Writing our own state management tools when needed. Redux is a tiny library. On a two year project, why not create your own custom state management system from scratch, one which makes the .NET people comfortable and has the features that match your project’s needs? It boggles my mind that many devs consider state management libraries to be something sacred, like a compiler, which you would never consider reimplementing yourself on an enterprise project.
Normally "roll-your-own" is bad advice. But in enterprise apps I can see all you needing is an API client with normalized caching (Apollo or `react-query` for REST), and store as much of your page state in your query string, and the rest in React Context. I would reach for Recoil if React Context performance became an issue.
But rolling your own comes with so much personal risk if things go wrong - not good for politics.
I have seen some developers follow patterns just because they are patterns. Once the community starts doing things one way that's it, even if it is a dumb way, the herd mentality causes the dumb way to become established. Redux is one of those dumb ways.
> Because 30% of the business logic was inside Redux-Saga, I marked it as a high risk.
Business logic should be written in POJO. Plain Old JavaScript Objects. Using a library such as Redux is a dumb way, but this is the community-embraced, herd-mentality way.
> I will not encourage using it for enterprise applications.
Use Web Components. Using the flavor-of-the-month JavaScript libs for a large application that must live years or decades is not justifiable.
Redux is really just a pattern for business logic using POJO - you have a function that takes an update and returns the new state. The library itself is about a hundred lines.
> Use Web Components. Using the flavor-of-the-month JavaScript libs for a large application that must live years or decades is not justifiable.
How is web components not just another flavor-of-the-month JavaScript library, and an unpopular one at that? Sure, it's part of the browser instead of something you load externally, but I'm not sure that changes things in any meaningful way. You're still tightly binding your code to something which may or may not remain popular.
That's actually a common practice. Files (modules, that is) are usually named after their principal export.
Enterprise applications are behemoths that without question will take longer to develop than the current webdev lifecycle and the most important thing for developers writing business logic is structure. Coding against a moving target is a recipe for failure.
I really wanted to use React for my current project and it would have sped up development. But I was afraid of this attitude of breaking things that pervades the ecosystem. I'm using HTML + Alpine.js. It's more work, but no breaking changes in libraries so far. I'm still not sure I made the right call. Only time will tell.
- eslint for style
- Webpack Externals/Module federation for build times
- Dependabot/renovate for automatic dependacies
- codemon for automated refactors
- WSL2 or vagrant VM + docker-compose for local dev
You need someone that like tinkering with this stuff instead of doing Jira points game. Give that person autonomy and your team would move faster.EDIT: forgot an important word
Well sure maybe superficially. There’s classes and then… that’s it. I don’t really see any other part of Angular that would help a (somewhat) experienced (pure) .NET developer in any way. There’s no batteries-included state management either.
Technology switches are hard. I don’t think the problem is with .NET specifically but with developers that stopped longing. Longing for new technologies, new algorithms, …
That was never going to go well.
> They want to use the .NET guidelines and design patterns in React.
Yes, you have .NET developers trying to be web developers. Totally different skill set. That's not going to go well, or quickly.
Rails is magic in that it's all ready. React+Redux+Typescript is great. I just don't want to make decisions here. I want to just make a web app. Like how Rails defaults to ActiveRecord and friends, is there something like that for Rails+React+Redux+Typescript?
I'm looking for:
* Few decisions for me to make
* It's relatively popular enough that there is a community around the whole thing
It's a huge productivity enhancer with Rails to be able to google "Rails do x" and someone has an answer to that. If I had to google "Ruby with X library and Y other library" I think I might commit suicide because the Rust experience is like that: "Use actix-web". Ah, and how do I use that with this other tokio based library. Oh you can't, because you need to make sure the runtimes are compatible.
I don't want all that.
It doesn't handle global state, but has tested examples for Redux[1] and various other libs that incorporate the server-side rendering and static site generation functionality that Next.js has.
[1]: https://github.com/vercel/next.js/tree/master/examples/with-...
How to do css, css-in-js etc How to build the api, rest graphql or what How to access your database How to do background jobs How to send emails How to organize the project structure How to do validations How to do translations How to do migrations
Other than this, it is great.
It's always the fuckload of third-party libraries we think we need.
Pick boring tech that's objectively simple and not an exercise in genius. mobx, today: apollo-client (if you have a graphql api).
I've never seen any other project stain a framework as much as Redux has done.
Also, he had a ton of organizational issues that have nothing to do with the tech.
Is there a good article that would summarize the backlash against Redux?
While I don't do front-end much anymore, Redux was such a productive tool for me when I was a contractor. I found it incredibly powerful and easy to work with, if cerebral for the uninitiated.
Meanwhile, I had the exact opposite experience with apollo-client and the apollo framework—very easy to get up and running, but a giant pita for doing anything complex.
Honestly, after using mobx, it's almost impossible to understand why Redux is popular. MobX is more concise, more performant, has a crazy amount of built-in optimizations, and lets you forget about tracing your crazy graph of relationships just to update some view.
Of course, mobx had "bad" (read: used decorators) syntax for a while, and only with MobX 6 did they clean it up, but boy oh boy is it clean now
The goals of it seem so misaligned with developer productivity.
It was small, elegant library for the sake of being small. Ultimate flexibility that can do everything, but then required building heaps of stuff on top of it, and favoring this immutable one-way flow that just complicated things riding on the coat tails of flux.
> I've never seen any other project stain a framework as much as Redux has done.
100%
Angular is just too cumbersome, though it gets an honorable mention.
Perhaps there is so much churn here because the correct way hasn’t been discovered yet?
The article pictures conflicts from different programming cultures. There isn't any attempt of acculturation mentioned in the article. Acculturation is important to keep everyone in the same page on what's the added value of React. You don't need people from .NET to get culture conflict, frontend dev that haven't got any previous experience with React and the likes, those who operates with jquery and left frontend world, for example, will also introduce culture conflict.
In the near beginning, "Where is the dependency injection? What do you mean by ‘There is no need for one?'".
The React developers seem to also not aware what's the significance of dependency injection, therefore the culture acknowledgement goes both way. While the term came from heavy-OOP environment, dependency injection can take a different form.
In React's world, it can utilize context or types from common module. Dependency injection is crucial in flattening deep components surfaces, which in turn makes them testable. And it's not exclusively for the React part. Testable code (with actual tests at STRATEGIC PLACES) makes it easy to increment on, because validating if the added code takes less effort. (Although automated tests at NON STRATEGIC places can make it worse).
“Why is the development slowing down?”.
I can imagine the author's frustration when "They want to use the .NET guidelines and design patterns in React". I've been in and out some cultures, React, NodeJS, Java, C#, C++, Golang, Android, Game development, Game Engine, Ecommerce, Identity management, Crypto, LL/system programming, infra. I can say that without running around and having enough persistence to break and remake cultures while avoiding ineffective compromises, things will not work.
CTO losing his temper and blaming for what's decided 2 years prior seems like either things have gotten a bit out of control or the environment is a bit toxic. That is if the story is told accurately. Maybe CTO has been constantly reminding the author along the way but only the climax is told because it is peak emotional. Either way, observability and control over the project is lacking. Also the added values of React and other dependencies being included in the project as the main UI library is not communicated well.
There are a lot of "should we use [x] lib" going on. The easiest principle is if a module changes a lot, don't depend on any lib that locks it in.
"Redux-Forms, Formiq, or Final-Form?" This smells, just because without delving deep into the library, Redux-forms seems to tightly couple redux state with, well, forms, which is, in React environment, usually closer to the UI side rather than the core logic side, and you want UI and logic layers to be able to change a lot relative to each other even if they don't.
On Redux:
Redux itself was a weird long-running phenomenon. Its placement relative to other components is a big misunderstanding. It's supposed to be a state container that can be either local or global, but the default `connect` API stamps it as a god object permanently in the eyes of the ecosystem. Not to mention countless of medium articles that encourage the pattern.
Its "middlewares" such as thunk makes stories hard to write as a single top-to-bottom functions. In one project we identified the risk of misunderstanding as a problem early in the project, therefore redux is removed. We didn't even got to touch redux-saga. We had to find a replacement, which is unstated and custom typed event emitter.
This buys us code explicitness, loose-coupling, less processes on increments, more accurate types (redux doesn't play nice with typescript's type system), but we had to pay with writing a lot of types (we are using typescript). It teaches us the concept of message passing ala kafka/rabbitMQ, as well as the importance of immutability, which is the core of redux, without redux API bureaucracy.
On React hooks:
React hooks was a departure to a more (a bit forced) functional programming. Some concept introduced is good as it encourage us to write in automata-based programming style.
Automata-based programming https://en.wikipedia.org/wiki/Automata-based_programming
But it has bad API design too. For example `use*` can't be written inside `if`. So are custom hooks. We have to be very careful to not place any hooks inside `if`. Writing with hooks needs either: 1.) experienced hooks developers, 2.) linter. You can install/write the latter as long as you become the former, which is a paradox. Had it introduced hooks as below things would be a bit better.
``` const SomeComponent = makeComponent( ({ context, props }) => { // context supplies useState and useEffect like APIs return ( <ChildComp /> ) }, { [stateName]: defaultValue } // the default state ) ```
The worse part of hooks introduction is that React's culture diverge, and so its users. A company can have people with and against hooks.
About the title, it should be "Using React the wrong way created roadblocks in our enterprise app".
I have this feeling that 2010+ has been this massive story arc and one day we will end up very close to where we started, back to something similar to jquery and vanilla JS because the platform improved. Just like how a React platform feature like context hooks deprecated Redux.
For frontend, if Typescript is standardized and shipped with browsers...see ya later beefy compiler toolchains.
For backend, Deno.
That Typescript with its current popularity is not shipped in browsers within 10 years seems super unlikely.
The funny thing with TS is that to get good typing, you start to write everything similar to Java/.NET with dependency injection etc. I resisted it for such a long time, but when you realize you want things typed, classes and all those patterns become necessary - see Nest.js/TypeORM for an example. It just makes everything cleaner and is easier to standardize patterns.
The post seems to have a bit of a "holier than thou" when dealing with naive .NET developers. I think that .NET devs living outside of our JS bubble probably have a lot of interesting criticism to offer. The retort that pops in your mind is "you just don't understand...this is how its done", but if they critiqued any number of the features that have been deprecated in React - they would have been right and us wrong. And even the creator of React said that moving away from classes made it to difficult and would have preferred not to have done it. My point is that JS is a bubble and we shouldn't be so sure of ourselves.
Also the fact that Apollo is the top API library at the moment, and doing optimistic updates and working with the cache is insanely complicated when ultimately you just want something like ActiveRecord on the client like how we use to do it with Backbone models. Redux and friends is also extremely verbose and complicated for no gain. I miss the simple mental model of Backbone - yeh there were problems, but at the end of the day I just want to write `User.getPosts()` and `User.setPost()` and be done with it. 90% of the time I don't actually need GraphQL selective querying and such, its just got such a big momentum and community behind it that I use it. And REST with `react-query` and `swr` is still extremely complicated. Sorry for the rant.
So I wonder if anyone has taken the time to predict when all the tools we use today will eventually be deprecated.
I personally went from spending probably 60% of my time fixing cross compatibility bugs to spending a few hours a year on it. We went from manual coding for cross browser support, to polyfills, to telling webpack to dynamically include polyfills to target the subset of browsers I care about with 2 lines of configuration. I can now determine the exact tradeoff between file size and audience reach. Yes, that came with some complexity. Yes, that tradeoff is 100% worth it. No, you do not have to use it.
This is how I feel about React. I've unintentionally built my own, shitty version of React at least half a dozen times over the last decade. The last time, maybe 4 or 5 years ago now, was an online file system browser which could contain tens or possibly hundreds of thousands of folders/files. The naive implementation wouldn't load. A less naive implementation took a few weeks to implement and seconds to load. The React rewrite took a day or two to write and loaded in milliseconds. It was less code, easier to understand, and a couple of orders of magnitude more performant!
Other languages don't have crazy build systems because they don't have to run the same code on multiple platforms made by multiple competing vendors on multiple operating systems for hardware ranging from a M1 to a refrigerator. If that's not you, not a problem, you can just write vanilla JS. If you don't have thousands of objects that you dynamically load that need to be turned into DOM Nodes, don't reach for React... If you just want a library that renders some DOM Nodes, thats fine too, use React and nothing else - you can even write react.createElement by hand and eschew JSX if so desired!
I would not choose to go back to the halcyon days of web dev where we didn't have dependencies and dependency management because we couldn't. At this point in my career, changing web tech has lead to a productivity increase of probably 10000%. There are some pain points, but we're working on it! Web tech, fuck yeah!