DEV Community

Pascal Schilp
Pascal Schilp

Posted on

The Cost of Convenience

Something I see happen time and time again in frontend development is developers reaching for conveniences. It may be the hot new tool in town, it may be existing tooling, but developers just love to take shortcuts. And this is fine! We all love to spend our time being productive, right? We'll just add this one little convenience that will surely make our lives better, never think about it again and move on.

The conveniences

When we talk about conveniences, we generally talk about non-standardisms or any kind of magical behavior. A useful rule of thumb is to ask: "Does it run natively in a browser?". A good example of this are imports, which often get subjected to magical behavior and transformed into non-standardisms, like the following examples:

import icon from './icon.svg';
import data from './data.json';
import styles from './styles.css';
import whatever from '~/whatever.js';
import transformed from 'transform:whatever.js';
Enter fullscreen mode Exit fullscreen mode

None of these examples will actually work in a browser, because they are non-standard. Some of you might have correctly spotted that a browser standard exists for two of the imports pointed out in the example, namely the Import Attributes proposal (previously known as Import Assertions), but these imports in their current shape will not work natively in a browser. Many of these non-standard imports exist for good reason; they are very convenient.

Other conveniences may include any kind of build-time transformations; like for example JSX. Nobody wants to write createElement calls by hand, but JSX will not run in a browser as is. The same goes for TypeScript. Developers evidently are very happy writing types in their source code (and will get very upset when you tell them you can use TypeScript without compiling your code), but alas, TypeScript source code does not run natively in the browser. Not until the Type Annotations proposal lands anyway, which is only stage 1 at the time of writing.

Using Node.js globals like process.env to enable special development-time logging is another convenience often added by libraries, but will also cause runtime errors in the browser when not specifically handled by adding additional tooling.

It is important to note that this is not to say that anything that doesn't run natively in the browser is wrong or bad. Exactly the opposite is true; It is convenient. Keep reading. It's also important to note that these are only some examples of conveniences.

The cost

The problem with conveniences is that they come at a cost. How easy is it to add this one little convenience that will surely make our lives better, never think about it again and move on.

It should come as no surprise to anybody that the frontend tooling ecosystem is complex, and in large part stems from the conveniences developers insist upon. When we apply a convenience to one tool, we have to now also make sure all of our other tooling plays nice with it, and enforce everything to also support anything. Whenever new tooling comes about, it is then also pressured into supporting these conveniences for it to ever be able to catch on, and to ease migrations to it.

But more concerningly, we become so accustomed to our toolchains and conveniences, that it often leads to assumptions of other people using the same toolchain as you do. Which then leads to packages containing conveniences to be published to the NPM registry. This, as you might have guessed, forces other projects to also adopt additional tooling to be able to support these packages that they want to use, and cause a never-ending spiral of imposed conveniences.

It is disappointing to see that we have still not learned from the mistakes made by the recently sunsetted starter kit of one of the most popular JavaScript frameworks over the past decade, when contemporary popular development tools are making the exact same mistakes as the one before it by enabling conveniences out of the box.

Where you apply conveniences, you apply lock in. What happens when the next, faster tool comes out? Will it support all of your conveniences?

The conclusion

Is this all to say that conveniences are bad? Are they not helpful, and not valuable? Should our tooling not be allowed to support conveniences? Should they be shunned, or should tooling not support them? Are they simply wrong? The answer is no. Conveniences have their merits and are undeniably valuable. But they come at a cost, and tools should absolutely not enable them by default.

Additionally, when you build for the lowest common denominator and don't rely on conveniences, your code will work anywhere. It ensures compatibility with new tools and web standards, eliminating conflicts. This practice is sometimes referred to as buildless development. While it may seem unnecessary to prioritize portability, the importance of this approach becomes evident when circumstances change; you might be right, until you're not.

And finally, you might actually find it refreshing to try frontend development without all the bells and whistles. Maybe you'll find that buildless development can get you pretty far, you'll often really only need a dev server with node resolution to resolve bare module specifiers, if at all. Maybe try it out some time.

Top comments (15)

Collapse
 
isaachagoel profile image
Isaac Hagoel

While I agree with the sentiment of "don't just use stuff without considering cost vs. benefit", I am not sold on "does the browser natively support it" as the key metric. The browser API is notorious for its weirdness and good intentions that are executed poorly (e.g. web components, drag and drop, modals, indexedDB ...) and I wouldn't treat it as some kind of gold standard :)

Collapse
 
justinfagnani profile image
Justin Fagnani

Uh, web components are not executed poorly - they are low level, but that's good. And you can use libraries that run in browsers with no special tool chain or fork of standard languages require that make writing web components very nice.

Collapse
 
thepassle profile image
Pascal Schilp

You think "runs in the browser" is not a good metric for code thats meant for the browser?

Collapse
 
isaachagoel profile image
Isaac Hagoel

Whether something runs in the browser or not without transpilation/compilation is not a very good metric, no. For example Svelte vs. vanilla JS

Thread Thread
 
thepassle profile image
Pascal Schilp

This is exactly the point though, when you use Svelte, you lock yourself in to Svelte and Svelte's toolchain. Svelte does not run in a browser natively. Again, that's not to say that Svelte is bad (it's very clearly not), just less portable than vanilla js. The same goes for other compilers, like Elm for example.

I do think its fair to say this operates on a bit of a different level, though, there's a very clear difference between building an app with Svelte, and publishing a package to NPM.

Thread Thread
 
isaachagoel profile image
Isaac Hagoel

Right. At the end it all boils down to cost benefit analysis

Collapse
 
mihneasim profile image
Mihnea Simian

I've seen frontend job applicants being able to use destructuring in parameter handling, but unable to differentiate between a function reference and a function call, as an argument for setTimeout.
Clearly they must be performing at a certain level, in their current role, but lacking the fundamentals. Relying on conveniences can have a huge cost on one's development and career as well.

Great read!

Collapse
 
tracygjg profile image
Tracy Gilmore

By the same token, I have interviewed candidates who have been through a React bootcamp and spent 3years on a React project but did not know what the this keyword did in JS or even what the CSS box model is.
This might be a controversial position but I fear when it comes to frontend developers we might have set the entry level too low.

Collapse
 
hendrikras profile image
Hendrik Ras

When ES6 came along we all jumped on board and started transpiling it because not all browsers supported it yet. But it seems like the transpiler became an unshakeable addiction. There's always that experimental feature that is too sexy not to use. And then there was TypeScript. Of course we have to use TypeScript!

Thanks for saying this. It needed to be said.

Collapse
 
technbuzz profile image
Samiullah Khan

Angular v16 has this esbuild support which makes the build process faster. But for now it doesn't support the Tailwind. But does support SCSS and css, natively.

If I have never relied on one tool for convenience (tailwind) I would have wanted other tool (esbuild) to play nicely together.

Collapse
 
romanbalzer profile image
Roman Balzer

Why shouldn't tool use conveniences by default? Many of them lower the entry barrier for people to get into development. Especially tool for non-devs.

Collapse
 
thepassle profile image
Pascal Schilp

Read the post :)

Collapse
 
romanbalzer profile image
Roman Balzer

I've read it. Have i missed something or missunderstood something?

You stated absolutly avoid conviences by default. My take on it is, "It depends on the tool" and "They help to reduce the entry barrier", so for me it's not a must to avoid them. (Thou I have to admit I interpreted convieniences a bit broader than just for JS, but also for tools like IDEs)

Thread Thread
 
jorenbroekema profile image
Joren Broekema

Okay you read it, I will believe you, but did you miss the part where this infinite and growing loop of imposing conveniences was mentioned? I believe that's your answer.