Stop Using JSON Config Files

A story about why we shouldn’t use tools to do what can be done with plain JavaScript

David Barral
Trabe
4 min readJun 1, 2020

--

Photo by Jose Aragones on Unsplash

Every major tool in the JavaScript world allows custom configuration using either JSON or JavaScript files (Babel or ESLint are good examples). Whatever the reason you may have to choose JSON, please don’t. Use JavaScript instead.

Learning from my own mistakes

Once upon a time I was setting up a complex monorepo. It contained several packages that shared common transpilation, linting and testing configuration. Some of these packages needed to tweak this config a little.

I firmly believe that less is more, so on my first try, I used JSON config inside the package.json. The shared configuration lived in a shared package that every other package used via the extension mechanism provided by the tool we were targeting (Babel for example):

So simple. Unfortunately, not every tool implements this extends mechanism.

Believing that the tools were lacking, I looked for related issues in Github. I wasn’t the only one asking for this to be supported. After a friendly debate, I realized that the maintainers would never consider the request. Why should they when they already provided a suitable extension mechanism: using JavaScript configuration files.

Oh boy! I was so wrong and they were so right. I was intoxicated by the promise of an all mighty package.json file with all my config and missed the point completely. Given my ruby background I should have known better at that time (the gemfile.rb has always been more flexible than the package.json as a tool for defining packages).

Once I embraced the JavaScript format, all my problems went away. My monorepo setup was beautiful and it has been refactored from time to time to be more simple and efficient.

Why you should also prefer JavaScript configuration

Mainly because JSON is a data format and JavaScript is just code. Code is evaluable (therefore dynamic) and composable. And there’s no need for any tool to do fancy stuff.

As a bonus, JavaScript configuration is commentable, testable, lintable and prettifiable. Maybe you don’t need to test your config files but you sure need to make them adhere to good practices and the same code conventions as the rest of your codebase does.

Let’s see some of these “features” using examples.

Easy overrides

If you require a configuration file, you can modify the returned object and re-export it.

Does your package needs an extra babel plugin? No problem.

Dynamic configuration

As I said, JSON is a data format, so it can’t be dynamic. If you want different versions of your JSON config, you have to use different files that may differ only slightly. Enter JavaScript. When a tool requires a JavaScript configuration file, the code is evaluated.

Do you need a plugin only in production? No problem.

Shareable configuration

There is a canonical way to share code in JavaScript: the npm package.

Write an appropriate package.json and npm publish it.

Once published you just require the package in every project you need it:

Comments

JSON does not support comments. Or, at least, they are not part of the JSON spec. You can use some kind of ugly hack like adding extra keys with comments.

JavaScript has real comments (both block and inline). You can put them wherever you want and are syntax highlight friendly.

Testable configuration

As I said before, you can test your config files. They are just code.

It’s up to you to decide if testing your tooling infrastructure adds value to a project. Suppose it does. Let’s test our dynamic config using Jest.

Be aware that config tests can be quite brittle. If you just need to ensure no one messes with the files you can use snapshot testing.

Summing up

Being wrong about JavaScript config files was one of the best things (tech-wise) that happened to me. It has made my life as a developer easier.

In this story I’ve shown some examples of what can be done with JavaScript config. Stuff that’s not easily done with JSON without tooling support. This may seem obvious, but trust me, it’s not.

I really don’t know why most JS tools still support JSON config. I’m ok with backwards compatibility and not breaking the whole internet, but maybe it is time to start issuing some deprecation warnings and phasing JSON out.

By sticking to only one format, most tools could drop all the code needed to provide custom extension and sharing mechanisms. If you have to choose just one format, better choose the one best suited to the task: plain JavaScript files.

--

--

David Barral
Trabe
Editor for

Co-founder @Trabe. Developer drowning in a sea of pointless code.