Hacker News new | past | comments | ask | show | jobs | submit login
Responsible JavaScript: Part I (alistapart.com)
132 points by wheresvic1 on Apr 15, 2019 | hide | past | web | favorite | 70 comments

We need to know the purpose we’re trying to serve, and only then can we build something that admirably serves that purpose—even if it isn’t exciting to build.

I wonder if there is a common mindset that the majority of web developers have which causes them to love overcomplexity so much; certainly it's there in other areas of programming, but it is not quite as prevalent. There seems to be a very strong "if it's not new it's bad" sentiment[1], and as a result, the amount of churn is also extremely high. What's so "exciting" about doing more with less?

As an aside, it is good to see that this article is completely readable without JS.

[1] I've received comments from "real web developers" that some of the JS I've written is "not modern enough" --- despite it working in more browsers and being over an order of magnitude less code than their proposed "proper web development" solutions. They are correct, I am not a "real web developer", but when I write JS it's usually because I have a problem to solve and don't have any other choice.

I am also a classic web developer, still using vanilla javascript and trying to do as much as possible with just html and css. I feel I can solve any problem fast, quick and with minimal amount of code and bugs. For the recent years I have hired a few javascript developers and a common pattern I see is that the reason why they want to use overcomplicated toolset, is because this helps improving their CV so they are easier to sell. CV building is a thing, and developers also want to stay relevant in the future.

For example I went through software developer job listings in my area. Of 100 listings, 40 of them are React specific, 2-3 Angular while maybe 5 mention any kind of frontend development like html/css/jquery. The rest is classical back end positions. There is a HUGE demand for frontend expertise these days.

If you as a consultant want to sell yourself as a kickass rockstar frontend developer, you want as much React experience as possible on your CV. Some will even turn you down because of the fear of damaging their CV by just doing vanilla javascript work.

Myself and most full stack devs in my circle using React used to do html/css/jquery before. Nobody misses the jquery days. As soon as you start fetching data from api and refreshing your UI you get into a mess. Let's not forget that most MVC frameworks from the era imply mixing server side rendering with some partial client-side rendering on UI updates. Re-rendering your html from templates client-side, re-binding your elements to its events... it's objectively worse both in runtime performance and development wise.

React just does the rerendering and re-binding for you - and does it way less efficient than if you hand coded it.

What you should be doing is just changing the parts that you know have changed. Letting react do the hard work will always lead to worse performance

Not really, at least in my experience. The re-binding really isn't the same as the jquery way. React reuses the same event handlers, how it's implemented is another story and not really important anyway. The other issue is the fact that in the old way it's implicit that there's a mix of server and client side rendering. Say you have a grid of data that was rendered server-side. Then you update a row, which posts to an api endpoint and you get a reponse that represents your new row. At this point there's only a couple of ways this could be done:

1. you get a json object which you pass to a javascript function which re-renders the row's html and re-binds all interactive elements. 2. You get server rendered html from the server, which then leaves you to call a js function to re-bind all interactive elements.

some classic problems with this approach: 1. some rows data may depend on the data of other rows... now you have to sync client and server side state! (huge problem). 2. Remember that initial server-side view? guess what, all interactive elements had to be bound to the javascript handlers initially. Now you need code to initialize the view which is different to the one you use to do the partial updates. 3. Yes, I dind't even mention that we could send server rendered html full of inlined handlers as in "onClick=myClickHandler()". Because this leads to problem #2 right away.

I'm not saying React and friends are perfect, but it does solve all of this, at least IMHO.

Yeah I dont know about that. If you've ever had to deal with optimizing event delegation and updating the DOM without causing massive repaints you'd change your tune.

> still using vanilla javascript and trying to do as much as possible with just html and css.

Thank you. As someone who only allows JS to run very, very sparingly (and even then only on sites that are, for one reason or another, actually indispensable to me), I appreciate this very much.

If a site requires JS to work, and if that site is something that is optional for me, then I won't use that site.

Ah, good old Resume Driven Development. I've seen it and even done a little of it.

> I wonder if there is a common mindset that the majority of web developers have which causes them to love overcomplexity so much;

This is, in turn, is a weird mindset. Are you suggesting that web developers are somehow unique in the software development space? Here's a hint: they aren't. The problems that web developers have to solve are relatively unique to the platform. When is 1MB of code a lot? This is not amount of code written, this is amount of code used. In python, it is not uncommon to import a library like `numpy` which will easily clock in 20+ MB for one library. Why don't people care about python dependency bloat? Because it doesn't have to be downloaded over HTTP like javascript. That is a unique feature of web development. What do you think would happen if developers around the world started complaining about using `numpy`? It's the same thing with libraries like `react`: they have no credibility because `react` is useful. It has nothing to do with web developer mindset, everyone wants to bring in libraries that make their lives easier.

>In python, it is not uncommon to import a library like `numpy` which will easily clock in 20+ MB for one library. Why don't people care about python dependency bloat?

Because some random Joe Schmoe can't replace numpy with a few lines of vanilla Pyton.

Because numpy has a governing organization and isn't just an arbitrary library some unknown developer dumped on NPM.

Because numpy is over a decade old and isn't any in danger of being superseded on the basis of not being fashionable.

Literally none of those things apply to React though.

  > I wonder if there is a common
  > mindset that the majority of
  > web developers have which
  > causes them to love
  > overcomplexity so much
We don’t love complexity, we love ease. The complexity is a side affect of us trying to make our job easy by `npm install`ing various tools/libraries/frameworks :)

Another problem is the web is inherently complicated, and people expect more and more from the web. We’re still working out how to best manage the complexity and increased demands.

Taking on a huge amount of dependencies only (potentially) makes your life easier up front.

You now get to experience all bugs and side effects for all projects you now took on "due to ease."

You now effectively maintain all those projects, instead of your own. You cannot go to your customers and say "well this library isnt working so neither is our website, and we can upgrade without it."

You also cannot go to your customers and say "well instead of using a popular library, we used our own and it broke and so did your site"

And more importantly, NIH leads to on-boarding issues. Many, many people are React/Angular/Vue developers, but how many are $INTERNAL_RECREATION_OF_REACT developers? By creating a new framework, you waste money (not just on reinventing the wheel and fixing bugs in your new wheel, but also on having every new-hire take even longer to get productive)

Code that you've written also tends to be code you have an understanding of, and thus much easier to debug than a maze of third-party dependencies.

The extreme aversion to "reinventing the wheel" leads to things like left-pad.

> I wonder if there is a common mindset that the majority of web developers have which causes them to love overcomplexity so much; certainly it's there in other areas of programming, but it is not quite as prevalent.

Is this really unique to (frontend) web developers? I've heard plenty of stories of people building tangled webs of microservices when a monolith would be fine, using Kubernetes to run their weblog, using Hadoop with small datasets, etc.

I once worked with a guy who, after looking at a solution provided by our team that not only worked but was fast and efficient, said, “This can’t be any good. You don’t have enough code.”

He was in a leadership position.

This way of thinking isn’t restricted to our industry. I see it in other areas as well. People naturally equate complexity with quality and actually have a hard time appreciating the beauty of a well-designed, well-thought out, efficient system. Why that is is beyond me.

> People naturally equate complexity with quality

Which is weird because, generally speaking, higher code complexity is a signal of lower quality.

It goes into why we need design systems, software architectures, libraries at all? Because of communication and managing complexity. You give 5 developers one single set of requirements, their approach to the problem likely to be drastically different. Could their solutions be effective? Very likely to be. But that's not large projects are about, they are about continuity of the projects without locking into developers.

For developers want to solve a problem quickly, you are correct - and more power to you because no one else (mostly) can understand your code. Job security FTW there. I think most of companies starting to realizing they can't keep people like you very long. You are both capable and stubborn (most likely). That's why job market is shifting towards mediumly skilled team and process oriented developers. Hope that makes sense.

> [1] I've received comments from "real web developers" that some of the JS I've written is "not modern enough"

I've said this in code reviews a few times. In ever case, it was because someone was using some construct that would have been needed in older Javascript versions, but was no longer necessary in whatever deployment we were supporting as a minimum. Sometimes it was from taking old Javascript conventions into Typescript. In ever case, the original code was a workaround for old bugs.

Can you cite an example?

Did you mean to write `What's so "exciting" about doing more with less?` I think the answer is obvious...

More on topic I think more context is needed on your anecdote. Was you developing a small tool that's likely to balloon into a suite of tools etc? There may have been a variety of other factors to consider whether it may be worthwhile investing into a framework in the long term

I'm not saying that your sentiment isn't at least a little true - but creating complex modern web applications is hard and frameworks CAN be the right decision depending on requirements.

RE: "not modern enough"

I often hear the following versions: "that's not the current paradigm" or, "that's not recommended"

> "that's not the current paradigm" or, "that's not recommended"

When I see these words, I think these are followers. They don't truly understand why they are doing what they're doing, but "everyone else" is doing it, so it must be good.

Those should not be ignored, but they should be immediately followed up with by "why?" because understanding why the old paradigm didn't work, or why something isn't recommended, is important knowledge to have. If you tune out when someone tells you no, without asking why, you haven't started learning yet. There might be great reasons for why the current paradigm is actually preferred, or why that code you wrote is actually really bad because a single edge case that just happens to be severe enough. Until you ask why, you won't know, and your decisions will not be informed decisions.

The sad part is, those are the answers to my question "why"...

Complexity in JavaScript is not a code issue, it's a UI issue. Complicated UI's necessitate frameworks, not developers. When a website hits a certain level of UI interactions, I arbitrarily say around 10 per page, then HTML/CSS/"A sprinkle of JS" becomes unsustainable. Shipping 400kb of React isn't ideal, but to manage your complexity it is responsible.

Let's say your page has the following: - Custom form validations - Custom styled <Select> tags - Forms that should show full lifecycle on submit without page refresh (form accepted, form error, sometimes API's return a 200 that is actually a failure :-/ ) - Inline editing of some user data. - Badges based on your users activity. - Notifications of new items. - Navigation styling that is JS powered in some way, or un-achievable or kind of a schlep with CSS (maybe the links are API powered :-/ ). - A table with sorting/filtering - Drag and drop reordering - Some type of chat window

Now let's increase complexity and say all those things respond in some way to changes in the other things.

I've built that page. That page is no longer a website. That page is an app and apps need structure.

The developer alone didn't decide the page needed all that. Chances are the business thought doing everything on one page made a strong business case. The UX team backed it up. The developer maybe agreed because they want a challenge.

There's no way this trend abates until complicated UI's fall out of fashion.

This is the common excuse given for bloated JavaScript usage but it ignores the realities of what is happening on the web. People are building simple blogs with JavaScript frameworks. People are building their 2 form field login page with JavaScript frameworks.

It's just inaccurate to take the most complex thing you can create and act as though that's the norm; it's not. Websites still exist, and people are using the most complex tech to create those too.

I ask in the spirit of friendliness, is this really an issue, or is this something that feels like one?

I'm hard pressed to imagine WordPress having login forms done in a JS Framework, and that's a big chunk of the web. If they are doing that, then you're right, it's totally unnecessary. But I'm guessing the folks at Automattic are optimizing this stuff for their clients (but I concede that I could be wrong here).

As far as blogs in these tech stacks, if they're developer blogs then that makes total sense. A dev blogging about React would probably choose React for their blog since that's a live production laboratory for any React code. I had a website in Ruby on Rails for years because I was a Rails dev and it was easy to try stuff out.

Are there any concrete stats on actual mismatch? Do we know how many recipe blogs are using Angular or React? My guess is their bloat is from tons of scripts and not from a developer using a tool that is wrong for the job. That bloat is at its heart a UI/business problem. Analytics, pop-ups, sharing links, referrals and that entire class of web objects IMO opinion are UI/business concerns, and they'll continue as long as folks find those things valuable.

Yes, it's a real issue. There's even a VC funded startup that specializes in a React based blogging tool: https://www.gatsbyjs.org/. If you work as a web developer there's just no denying it; using a SPA framework has become the default for all new projects, full stop, regardless of the type of project.

For data, look up often reported stats on JS size.

When did progressive enhancement become a bad thing? Gatsby generates static files with functional markup, then layers React on top of that for an even better experience. Try loading e.g. https://overreacted.io with JavaScript disabled. It works perfectly.

Pick any article on that page. Scroll to the bottom and refresh. In a tradition site the browser would remember your scroll position. Here it doesn't, likely due to using client-side routing in JavaScript. So instead you're taken to the start of the article each time.

It's this type of detail that's really difficult to get right when you choose to opt-out of decades of iteration and do everything yourself.

Sure, but "not retaining scroll position on refresh" is hardly a case of throwing the baby out with the bathwater.

You can't dismiss this bug like that. Having multiple tabs open and having those tabs get taken out of memory and needing to refresh is a very common thing to happen. This is a bad bug for this particular website.

Now, you said that by layering a SPA on top that an "even better experience" is provided. What exactly is the better experience? Just navigating around the site a bit I don't see anything particularly dynamic about it at all.

Actually, I just disabled JavaScript and tried reloading on a page, and that bug happens anyway. Not sure why that's happening, but it's not JavaScript. And considering it doesn't inhibit access to the content at all, "bad bug" is a gross overstatement.

As for the better experience: faster loading and dark theme?

Gatsby is an amazing developer experience, definitely not something I would use as an example of an "issue".

This is just the problem our industry has. Hammer is popular, everyone learns hammer. Now all problems are solved with a hammer.

I think there is always going to be a certain tension between two conflicting desires:

A) The desire to use the right tool for the right job

B) The desire to have fewer, more versatile tools

It's understandable that people don't want to learn dozens of different languages, frameworks, and libraries. There is a real cost to gaining knowledge and experience with all those tools, and a real benefit to knowing a single tool really well.

On the other hand I often find more tailored tools can be much more powerful for their suited tasks. But then again it's also true that the scope of projects is always shifting, so sometimes you can outgrow the specific use case of a tool.

Anyway, I would say it isn't clear (to me at least) that our industry has a "problem."

Exactly. There is a place for these tools, the key is having the knowledge to know when it makes sense to take the next step, and when it's just overkill.

If you have a site delivering mostly static content, obviously use the bare minimum JS.

However if you have a lot of reactive forms, interactivity etc, while it can be done with plain Javascript and HTML, I've seen way more buggy DOM manipulation/jQuery soup than not, even from experienced devs. Add in a large team working on separate features and code quality and UI consistency goes in the toilet. The frontend libraries at least can bring some structure and common patterns that can slow down this debt, at a library size similar to jQuery.

It's also important to remember you don't have to go all in. If your site is mostly static with a few highly interactive components, you don't need a SPA Webpack setup with a 50MB node_modules directory. Tools like VueJS can be dropped incrementally on a server rendered application, and you can "step up" in terms of libraries, common components and build process only as needed.

Me and an earlier colleague had the same fight, that he could rewrite my 10000 lines of vanilla JavaScript code for interactive UI with less code and less bugs if it was written in React.

The React infrastructure ended up with more than 10000 lines of code, more bugs, and he spent at least twice the amount of time to deliver.

The main reason he failed, was that he over-engineered his solution.

As long as you are not experiential as the developer of react, it is likely your 10000 lines of code would create way more bugs than the 10000 lines of code react team wrote, it just not explode yet, while your colleague only need to debug the extra 1000 lines of code he wrote.

> Most layout issues JavaScript packages attempt to solve, like box placement, alignment, and sizing, managing text overflow, and even entire layout systems, are solvable with CSS today.

This paragraph has surprising links. "Managing text overflow" links to Shave, a library for truncating multiline text[0]. Last time I checked, CSS was capable of truncating single-line text, but could not truncate multiline text (the line-clamp rule is still not universally supported). The first link in that paragraph is to a flexbox polyfill, and obviously, there's a reason why people use polyfills.

[0] - https://www.npmjs.com/package/shave

Yea there's plenty of benefits using a truncation library (we're currently using react-lines-ellipsis) over just css truncation. More control over how the truncation happens, callback so you can do more stuff on the condition that truncation has occurred, multi-line truncation as you mentioned, etc etc.

I get the feeling that most of the time when people are complaining about unnecessary libraries they simply haven't personally run into the problem that the library solves yet.

This all started with angular imho. There was a time when structure, layout and logic were more cleanly separated. Angular blew this up with <ng-xxx> tags (which was a step backwards towards PHP imho) and this has been driven forward by other frameworks since. It surprising to me how so many people can talk about shadow dom but can't name any of the HTML5 apis or even more than a few tags and what they do (much less anything about CSS3).

> There was a time when structure, layout and logic were more cleanly separated.

Yes, and what many developers started to realize is that this separation is not very useful (at least for proper web applications, as opposed to websites with mostly static content). Conversely, separating the building blocks of application into components where structure, layout and logic commingle is very useful.

I realize not all developers agree with eschewing structure/styling/logic separation. But many do and it's important to realize that they do so consciously and not because they don't know what they're doing.

Angular was one of the first (perhaps the first, not sure) libraries to move towards this direction. It brought a lot of accidental complexity with it, which is understandable as these concepts were only starting to be fleshed out in the web world.

It was React. React made it so that you could outsource your markup to libraries, and the community adopted the mindset enthusiastically. Along with that was a focus on composability over what actually gets produced.

React has always been about making an abstraction layer of its own; to remove focus away from the underlying platform. A metaplatform, if you will. That explains the problems described in this article, it explains the desire for CSS-in-JS (which despite arguments for, is only popular in React and no where else).

So what we've wound up with is a generation of developers who are really good at the lego-block building aspects that React provide (which are valuable) but know next to nothing about HTML or CSS.

I don't really think React is old enough to say developers know next to nothing about HTML/CSS.

CSS-in-JS still requires knowledge of CSS, albeit a subset usually. The same could be said for JSX and HTML.

If you can work with React you can work with raw HTML/CSS. It's just you have all the problems that come with those that maybe some developers haven't had the misfortune to deal with.

The React workflow gives you a right sense of direction, where usually you'd be left on your own.

It sounds like you agree with me. Yes, you have to know some things. Developers who came in in this culture know that inputs are for typing things and that divs are for block level elements and span for inline ones. That's a far cry from knowing HTML.

There are many developers who don't really know anything about the head element because its something their tools generate and they don't touch.

Yeah I didn't really know where I ended up once I finished the response. I suppose I partly agree with you. If the developer was able to learn the React ecosystem, they'll be able to learn the more advanced parts of dealing with a pure HTML/CSS project if they need to. I think the form of a middle-out approach to learning is better than working from "fundamentals" you may not even need. There's so much to learn in the web ecosystem, a lot of it being optional. I think starting with React and working backwards and forwards is a just-fine strategy.

One of my interview questions is "how do you organize logic and state in a react app?" and about 19/20 candidates put their business logic in their view components. I believe the root of the problem is the ecosystem of terrible react tutorials that are targeted at beginners so can't introduce complex architecture. If you spend some time reading react blogs you'll see that almost all of them put their API requests and business logic inside component lifecycle methods. The flood of bootcamp grads has made hiring competent front end devs nearly impossible (not to slander bootcamp grads; I've met a few that are brilliant).

>you'll see that almost all of them put their API requests and business logic inside component lifecycle methods

Edit: (I rephrased this post) I understand that logic often makes sense to break out between presentational and container components, and I understand that sometimes api / service calls should be broken out into their own files, but everything I've read states that api logic should be called from ComponentDidMount.... you are saying that you shouldn't make api calls, from component lifecycle methods whatsoever?

I'm not sure what the alternative is?

Yes, sorry I should have been more specific. You always have to kick off the process from somewhere, so your lifecycle methods will call out to wherever you choose to keep your non-UI application logic. There are a million ways you could implement that, from a state management library or just good old OOP classes and methods. If your code is well structured, you should be able to swap out your component framework without having to refactor any of your business logic.

When I ask this question I'm just looking for any answer that displays some knowledge of separation of concerns. Surprisingly, so far only a few out of dozens of applicants have been able to do so. I should also point out that these applicants are not applying for junior positions and all have ~5 years of front-end experience on their resumes.

I'm also curious why my comment above has been attracting downvotes. Did I say something rude or controversial? (I'm not complaining, just curious)

The alternative is side-effects. Pick your poison, redux-sagas, redux-thunk, etc.

I prefer redux-sagas because generators fit the bill perfectly, and they test easy, and I'm not a huge fan of Observables.

The components dispatch an action, and the heavy-lifting is done by the side-effects library that listens for that action, and does any API calls, as well as dispatching any more actions.

I would also love to see resources that detail how to separate business logic from view components. As a junior dev, I know it's the right thing to do but I'm not sure how. Is it as simple as passing props into a utils file?

Any links would be greatly appreciated.

So I'm aware of the difference between presentation and compositional components, but the original poster was claiming service calls shouldn't be in lifecycle methods? Abramov puts his api calls into ComponentDidMount in his egghead.io videos...

That doesn't scale after awhile. Generally the next step is putting your business logic in HOCs or Redux thunks or sagas. Now it can be dropped in hooks too.

Use container for the business logic and the component itself just for the view logic. So for example you would have <ToDoContainer /> for the business logic and <ToDoComponent /> for the view logic. Do i get the job? :P

That's just as shit. You need to build an API layer and a service/utility layer. These should be completely separated from React-land. Ideally you should be able to change UI frameworks without altering or moving any of your business logic.

>Ideally you should be able to change UI frameworks without altering or moving any of your business logic.

That's just as shit imo, adding unnecessary complexity for the sake of adding it. If you are choosing a framework, you are betting on it, why complicate things. Might as well write in Vanilla JS at that point.

It adds easier testability - you can test the logic outside of the framework.

These are valid concerns and fortunately there are already examples of potential solutions being developed:


Not saying this specific framework is going to be a success, but so far it both:

- Is mostly "batteries included".

- Indeed does create pretty small bundles.

The really nice thing about Svelte is that it treeshakes really well. I wrote a Firefox extension with Svelte (v1), and when Svelte v3 becomes stable I will be very excited to upgrade.

Benchmarking on low-end devices to prove your point is situational at best in my opinion. For example if you work at a luxury ecommerce brand, you can assume that most users who actually are going to buy something are going to be using a flagship model device.

> if you work at a luxury ecommerce brand

That's a big IF right there.

You're dismissing the author's point simply based on one hypothetical. In general, the author is right. JavaScript frameworks are being abused and developers don't care about the download size of their web pages, and it's terrible.

If you're on a desktop with a wired internet connection, then yeah, it's not really going to matter. But if you're on a 3 year old low-end mobile device on a spotty 3G connection, it's significant.

At first glance, I thought it was yet another 'do not use JavaScript at all because it is too bloated while ignoring all real world use and claiming everything can be done by css' click bait article. But this article actually considering real world use, making the point valid instead some silly useless statement. And it also does provide some useful suggests and making its points strong. Probably the best article of this kind I saw recently

Here is a "Real World" comparison of Front End Frameworks, which includes payload size.


As i realized, the difference between a website and a web app is that, a web app is also a state machine. A website is stateless.

So, if your state machine is complicated, the web app is also complicated. As it's so hard to modify even a small portion of a mess.

Such are the contradictions of the web that we shun constant code churn while at the same time giving full-throated endorsements of Service Workers.

Anybody else has issue with the side banners being on top of the text in the Firefox?

TL;DR: Use the platform

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact