Skip to content

Commit

Permalink
feat(docs): update lint in handbook (#5812)
Browse files Browse the repository at this point in the history
  • Loading branch information
tknickman committed Aug 28, 2023
1 parent 8be4001 commit 5e028d3
Showing 1 changed file with 66 additions and 19 deletions.
85 changes: 66 additions & 19 deletions docs/pages/repo/docs/handbook/linting/eslint.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { Tabs, Tab } from "../../../../../components/Tabs";
import Callout from '../../../../../components/Callout'

# ESLint in a monorepo

## Installing ESLint

Keeping a single version of ESLint is recommended for simplicity. Because of this, we suggest installing ESLint as `devDependency` at the root of your monorepo, or utilizing a tool like [syncpack](https://jamiemason.github.io/syncpack/) to maintain the same version across workspaces.

## Sharing config

Sharing an ESLint config across workspaces can be a boon to productivity by making all your workspaces more consistent.
Expand All @@ -18,47 +23,85 @@ apps
└─ .eslintrc.js
packages
└─ eslint-config-custom
├─ index.js
├─ next.js
├─ library.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.
Our `eslint-config-custom` file contains two files, `next.js`, and `library.js`. These are two different ESLint configs, which we can use in different workspaces, depending on our needs.

Let's investigate the `next.js` lint configuration:

```js filename="packages/eslint-config-custom/next.js"
const { resolve } = require("node:path");

const project = resolve(process.cwd(), "tsconfig.json");

/*
* This is a custom ESLint configuration for use with
* Next.js apps.
*
* This config extends the Vercel Engineering Style Guide.
* For more information, see https://github.com/vercel/style-guide
*
*/

```js filename="packages/eslint-config-custom/index.js"
module.exports = {
extends: ["next", "turbo", "prettier"],
extends: [
"@vercel/style-guide/eslint/node",
"@vercel/style-guide/eslint/typescript",
"@vercel/style-guide/eslint/browser",
"@vercel/style-guide/eslint/react",
"@vercel/style-guide/eslint/next",
// turborepo custom eslint configuration configures the following rules:
// - https://github.com/vercel/turbo/blob/main/packages/eslint-plugin-turbo/docs/rules/no-undeclared-env-vars.md
"eslint-config-turbo",
].map(require.resolve),
parserOptions: {
project,
},
globals: {
React: true,
JSX: true,
},
settings: {
"import/resolver": {
typescript: {
project,
},
},
},
ignorePatterns: ["node_modules/", "dist/"],
// add rules configurations here
rules: {
"@next/next/no-html-link-for-pages": "off",
"import/no-default-export": "off",
},
};
```

It's a typical ESLint config, nothing fancy.
It's a typical ESLint config that extends the [Vercel styleguide](https://github.com/vercel/style-guide), nothing fancy.

The `package.json` looks like this:

```json filename="packages/eslint-config-custom/package.json"
{
"name": "eslint-config-custom",
"main": "index.js",
"version": "1.0.0",
"dependencies": {
"eslint": "latest",
"eslint-config-next": "latest",
"eslint-config-prettier": "latest",
"eslint-plugin-react": "latest",
"eslint-config-turbo": "latest"
"license": "MIT",
"version": "0.0.0",
"private": true,
"devDependencies": {
"@vercel/style-guide": "^4.0.2",
"eslint-config-turbo": "^1.10.12"
}
}
```

Two things are notable here. First, the `main` field points to `index.js`. This allows files to easily [import this config](/repo/docs/handbook/sharing-code#anatomy-of-a-package).
```

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`.
Note that 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

Expand Down Expand Up @@ -99,11 +142,15 @@ We can then import the config like this:
```js filename="apps/web/.eslintrc.js"
module.exports = {
root: true,
extends: ["custom"],
extends: ["custom/next"],
};
```

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.
By adding `custom/next` to our `extends` array, we're telling ESLint to look for a package called `eslint-config-custom`, and reference the file `next.js`.

<Callout type="info">
You can avoid specifing the file by setting the entrypoint for your package as the file to load. For example, setting `main: 'next.js'` in the `package.json`, could be loaded as simply `extends: ["custom"]` in your `.eslintrc.js`.
</Callout>

### Summary

Expand Down

1 comment on commit 5e028d3

@vercel
Copy link

@vercel vercel bot commented on 5e028d3 Aug 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.