ESLint in a monorepo
Sharing config
Sharing an ESLint config across workspaces can be a boon to productivity by making all your workspaces more consistent.
Let's imagine a monorepo like this:
apps
├─ docs
│ ├─ package.json
│ └─ .eslintrc.js
└─ web
├─ package.json
└─ .eslintrc.js
packages
└─ eslint-config-custom
├─ index.js
└─ package.json
We've got a package called eslint-config-custom
, and two applications, each with their own .eslintrc.js
.
Our eslint-config-custom
package
Our eslint-config-custom
file contains only a single file, index.js
. It looks like this.
module.exports = {
extends: ["next", "turbo", "prettier"],
rules: {
"@next/next/no-html-link-for-pages": "off",
"react/jsx-key": "off",
},
};
It's a typical ESLint config, nothing fancy.
The package.json
looks like this:
{
"name": "eslint-config-custom",
"main": "index.js",
"dependencies": {
"eslint": "latest",
"eslint-config-next": "latest",
"eslint-config-prettier": "latest",
"eslint-plugin-react": "latest",
"eslint-config-turbo": "latest"
}
}
Two things are notable here. First, the main
field points to index.js
. This allows files to easily import this config.
Secondly, the ESLint dependencies are all listed here. This is useful - it means we don't need to re-specify the dependencies inside the apps which import eslint-config-custom
.
How to use the eslint-config-custom
package
In our web
app, we first need to add eslint-config-custom
as a dependency.
{
"dependencies": {
"eslint-config-custom": "*"
}
}
We can then import the config like this:
module.exports = {
root: true,
extends: ["custom"],
};
By adding custom
to our extends
array, we're telling ESLint to look for a package called eslint-config-custom
- and it finds our workspace.
Summary
This setup ships by default when you create a new monorepo with npx create-turbo@latest
. You can also look at our basic example to see a working version.
Setting up a lint
task
We recommend following the setup in the basics
section, with one alteration.
Each package.json
script should look like this:
{
"scripts": {
"lint": "eslint"
}
}