Reuse your eslint/prettier configurations in a monorepo with Lerna

Mathias Silva
React Brasil
5 min readNov 15, 2020

--

One of the most frustrated situations in the programming world is to rebuild or recreate something which you’ve already done before and don’t remember how to do anymore. It's certainly a big waste of time and I am, as every lazy programmer, constanly looking for ways to avoid these situations as much as possible.

In one of my personal projects, I catch myself again a new eslint/prettier configuration. Although it wasn't a hard task to do, I needed to create the files and search in my previous projects about how to enable and disable specific rules which I’ve used before. I realized that it was the moment for a change.

With that in mind, I came up with the idea of creating a monorepo and making each of my configurations as a NPM package. It ended up bringing me the facility of just making them as dependencies in my projects and adding a line in each of the eslint/prettier files, which was an acceptable result.

In this article, I'm going to demostrate how to reuse these configurations in a simple Node project and apply some rules. I choose no-used-vars, just to illustrate the concepts I've just mentioned. In addition, I used Lerna to manage the creation and versioning of the monorepo.

Monorepo and Lerna

Basically, a monorepo is a repository where you can store many packages. Some of the main advantages are more reusability and dependency management. There are plenty of tools to help us create monorepos as you can see here, but for the actual Node environment, Lerna proved to be quite satisfactory.

As the documentation says, Lerna is a tool for managing JavaScript projects with multiple packages. It makes our life easy providing commands for organizing, linting, testing and building the packages in our monorepos. So, let’s use it to create the basic structure.

$ mkdir lint-config
$ cd lint-config
$ npx lerna init

The last command shown above creates the basic structure a Node project including the package.json and lerna.json files. The lerna.json file contains basically the global version of the packages and the path in which they will be stored, as you can see below.

In order to create shareable configurations we just need to make sure the package’s name begins with eslint-config. Particularly, I like to provide a scoped name for each package which makes the importing process more declarative and organized. As a scoped name I used my username in NPM, but you can replace as your wish. Accordingly, we can create the package for eslint configuration.

$ lerna create @mathias5r/eslint-config

In the same way, to share prettier configuration, we just have to make sure the package’s name begins with prettier-config.

$ lerna create @mathias5r/prettier-config

Before continuing, let’s clean the project up. We can now delete the auto-generated folders __tests__ and lib because they won’t be used in our context. We can also remove the remaining properties in the package.json. Note that our entrypoint is index.js now, as you can see below.

Eslint/Prettier Config

Eslint and Prettier are code linters and formatters, respectively. They help us to make a better and cleaner code. After using them for the first time, you will probably want to use them for your next projects. So firstly, let’s create the eslint configuration. To do that, we need to add the eslint as a development dependency which is going to be also included in the Node project.

$ lerna add eslint packages/eslint-config --dev

After that, in the eslint-config-react folder, we can create the eslint config file named index.js as mentioned before. Here, it’s just necessary to extend the eslint:recommended which is a subset of core rules that report common problems and provide no-unused-vars rule.

In the same way, we also need to add prettier as a development dependency in our project.

$ lerna add prettier packages/prettir-config --dev

To illustrate the prettier’s actions, we can specify some rules like shown below.

Publishing

For the publishing steps, I’m considering that you have NPM and github accounts. By the way, be free to choose package and repository managers as you wish. You will just have to adjust the commands below for your scenario.

To introduce the steps needed to be done here, we need to create a git repository to store our monorepo and relate each of the local packages to a NPM package. Let’s begin with logging in the NPM’s account and specifying the scope.

$ npm login –scope mathias5r

It will request your corresponding credentials. After that, we can create a new git repository, Lerna will explicitly publish packages tagged in the current commit. This way, it’s easy to track the code in each major version. Remember to replace your username in the commands below.

$ git init
$ git add .
$ git commit -m “Initial commit”
$ git remote add origin git@github.com:username/reponame.git
$ git push -u origin master

In the lerna.json file we can see that the version specified is 0.0.0, however in our context this is not a valid version because, as the documentation says, NPM uses semver to parse version structures. So, let’s specify the first major version of all the packages.

$ lerna version major

It will change the version to 1.0.0. Finally, we can publish our packages.

$ lerna publish from-git

Testing

Last but not least, we need to test our configurations in a project which demonstrates the rules we’ve been specifying. Firstly, let’s create a new Node project and install the package as dependencies.

$ mkdir test-project
$ cd test-project
$ npm init -y
$ npm install @mathias5r/eslint-config-react --dev
$ npm install @mathias5r/prettier-config-react --dev

In order to apply the specified rules, we need to create the corresponding files and extend the configurations as you can see below.

  • Eslint (.eslintrc)

Result:

  • Prettier (.prettierrc)

Result:

Conclusion

The proposed scenario showed a strategy for organizing, reusing and integrating eslint and prettier configurations for your new projects. From here, you are free to add and customize your own rules and create a new version of the packages.

One advice is to make packages with the corresponding configurations for more specific contexts, like react or typescript, which can have different rules. An example code can be found in this repository @mathias5r/lint-config-mathias.

If you want to see more of this content buy me a coffee:

--

--