Reputation: 604
I have created basic next.js app using "npx create-next-app" and .eslintrc.json file created to add eslint rules.but it's not working.how to add linting rules to nextjs config
{
"env": {
"browser": true,
"es6": true
},
"extends": [
"standard"
],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly",
"React": "writable"
},
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 2018,
"sourceType": "module"
},
"plugins": [
"react"
],
"rules": {
"react/react-in-jsx-scope": "off"
}
}
I have tried this solution - https://medium.com/@joelmasters/setting-up-eslint-for-nextjs-37163d4cabaa
Upvotes: 24
Views: 66286
Reputation: 49150
NextJS now has official guide to add eslint to project: https://nextjs.org/docs/basic-features/eslint Additionally you need to install ESLint extension.
Also, If you're looking for ESLint with typescript support: https://gourav.io/blog/nextjs-cheatsheet
Install ESLint
npm i eslint --save-dev
Install ESLint plugins:
npx install-peerdeps --dev eslint-config-airbnb
Above single command will install 6 plugins: eslint-config-airbnb
, eslint-plugin-import
, eslint-plugin-react
, eslint-plugin-react-hooks
, and eslint-plugin-jsx-a11y
. You can also install these plugins individually.
Install babel eslint
npm i -D babel-eslint
Install prettier plugin (optional, so that prettier doesn't mess up with linting)
npm i -D eslint-config-prettier eslint-plugin-prettier
Your "devDependencies" should look something like this:
"devDependencies": {
"babel-eslint": "^10.1.0",
"eslint": "^6.8.0",
"eslint-config-airbnb": "^18.1.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-prettier": "^3.1.3",
"eslint-plugin-react": "^7.20.0",
"eslint-plugin-react-hooks": "^2.5.1"
}
Now, create a file .eslintrc.json
at root of project.
Paste below config:
{
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"node": true
},
"parser": "babel-eslint",
"extends": [
"eslint:recommended",
"airbnb",
"airbnb/hooks",
"plugin:react/recommended",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:jsx-a11y/recommended",
// "plugin:react-hooks/recommended",
// always put prettier at last
"prettier"
],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaFeatures": {
"jsx": true // enable linting for jsx files
},
"ecmaVersion": 11,
"sourceType": "module"
},
"settings": {
"react": {
"version": "detect"
}
},
"plugins": ["react", "react-hooks"],
"rules": {
// NextJs specific fix: suppress errors for missing 'import React' in files for nextjs
"react/react-in-jsx-scope": "off",
// NextJs specific fix: allow jsx syntax in js files
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }], //should add ".ts" if typescript project
"react/display-name": 1
}
}
Also, install ESLint extension for VSCode.
Reload VSCode window once to get proper linting
ESLint will automatically start detecting errors/warnings in *.js
and *.jsx
files. If that's not the case then either your project has no linting errors or ESLint is not properly setup.
To test if linting works run eslint command in terminal with folder path i.e. eslint pages/**
and notice output.
To disable linting of some files/folders you can create a .eslintignore
at the root of project.
.eslintignore
:
# don't ever lint node_modules
node_modules
# don't lint build output (make sure it's set to your correct build folder name)
dist
# don't lint nyc coverage output
coverage
Finally, you can also add linting to scripts
in package.json
as a part of your build/deploy process:
"scripts": {
"lint": "eslint ./components/** ./pages/** -c .eslintrc.json --ext js,jsx",
"lint-fix": "eslint ./components/** ./pages/** -c .eslintrc.json --fix --ext js,jsx",
}
See my current ESLint configuration for NextJS
Typescript project: https://github.com/GorvGoyl/Personal-Site-Gourav.io/blob/main/.eslintrc.js
Upvotes: 37
Reputation: 382512
Official in-tree examples
As mentioned by GorvGoyl, some better integration was added around Next.js 11.
Although there is documentation at: https://nextjs.org/docs/basic-features/eslint being a eslint newbie I just couldn't understand what I was supposed to do, so I just looked under examples/ and found some actual working code:
examples/with-eslint
https://github.com/vercel/next.js/tree/v12.0.7/examples/with-eslint
Minimal eslint example.
The setup contains:
package.json
{
"name": "with-eslint",
"version": "1.0.0",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"license": "MIT",
"dependencies": {
"next": "12.0.7",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"devDependencies": {
"eslint": "^7.24.0",
"eslint-config-next": "12.0.7"
}
}
.eslintrc
{
"extends": "next",
"root": true
}
pages/index.js
const Home = () => (
<div>
<script src="https://fake-script.com" />
<p>Home</p>
</div>
)
export default Home
For example doing:
cd examples/with-eslint
npm install
npm run lint
gives the desired error:
3:5 Warning: External synchronous scripts are forbidden. See: https://nextjs.org/docs/messages/no-sync-scripts. @next/next/no-sync-scripts
We can modify pages/index.js a bit to add some more cases that we might want to fail:
import React from 'react'
const Home = () => {
let s = 'abc'
s = "abc"
let unused
if (false) {
React.useEffect(() => 1)
}
return (
<div>
<script src="https://fake-script.com" />
<p>Home</p>
</div>
)
}
export default Home
and the results are:
"
vs '
on strings: uncheckedunused
unused variable: uncheckedReact.useEffect
: checked. I think this is because it includes the 'plugin:react-hooks/recommended',
at: https://github.com/vercel/next.js/blob/v12.0.7/packages/eslint-config-next/index.js#L12examples/with-typescript-eslint-jest
https://github.com/vercel/next.js/tree/v12.0.7/examples/with-typescript-eslint-jest
Exmple also with typescript.
Note that this example cannot be run in-tree otherwise it fails with:
ESLint couldn't find the plugin "eslint-plugin-jest".
which is must be picking up from repo toplevel:
The plugin "eslint-plugin-jest" was referenced from the config file in "../../.eslintrc.json#overrides[0]".
you have to first copy it outside somewhere like:
cp -rv examples/with-typescript-eslint-jest /tmp
cd /tmp/with-typescript-eslint-jest
But I think this examples is a bit outdated as it is not using the"
"extends": "next",
preset.
My recommended Next 12 typescript + prettier setup
Since the in-tree "examples/with-typescript-eslint-jest" doesn't look very up-to-date, here's a version of it that should be (just without jest):
package.json
{
"name": "with-eslint",
"version": "1.0.0",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start",
"lint": "next lint",
"format": "prettier --ignore-path .gitignore --write .",
"type-check": "tsc"
},
"license": "MIT",
"dependencies": {
"install": "0.13.0",
"next": "12.0.7",
"react": "17.0.2",
"react-dom": "17.0.2"
},
"devDependencies": {
"@types/node": "12.12.21",
"@types/react": "17.0.2",
"@types/react-dom": "17.0.1",
"eslint": "8.5.0",
"eslint-config-next": "12.0.7",
"eslint-config-prettier": "7.2.0",
"eslint-plugin-prettier": "4.0.0",
"prettier": "2.5.1",
"typescript": "4.5.4"
},
"prettier": {
"printWidth": 80,
"semi": false,
"singleQuote": true
}
}
.eslintrc.json
{
"extends": ["eslint:recommended", "next", "prettier"],
"plugins": ["prettier"],
"rules": {
"prettier/prettier": "error"
}
}
tsconfig.json (autogenerated by Next when you run npm run dev
)
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
],
"exclude": [
"node_modules"
]
}
.gitignore
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
# vercel
.vercel
# typescript
*.tsbuildinfo
pages/index.tsx
import React from 'react'
const Home = () => {
let n: number
let s = 'abc'
s = "abc"
let unused
if (false) {
React.useEffect(() => 1)
}
return (
<div>
<script src="https://fake-script.com" />
<p>Home</p>
</div>
)
}
export default Home
With this setup doing:
npm run lint
catches all issues as we would like:
4:7 Error: 'n' is defined but never used. no-unused-vars
6:3 Error: 's' is assigned a value but never used. no-unused-vars
6:7 Error: Replace `"abc"` with `'abc'` prettier/prettier
7:7 Error: 'unused' is defined but never used. no-unused-vars
8:7 Error: Unexpected constant condition. no-constant-condition
9:5 Error: React Hook "React.useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render. react-hooks/rules-of-hooks
13:7 Warning: External synchronous scripts are forbidden. See: https://nextjs.org/docs/messages/no-sync-scripts. @next/next/no-sync-scripts
The prettier errors can be fixed automatically with autoformatting:
npm run format
which automatically patches for us:
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -3,7 +3,7 @@ import React from 'react'
const Home = () => {
let n: number
let s = 'abc'
- s = "abc"
+ s = 'abc'
let unused
if (false) {
Running:
npm run type-check
catches the type error:
pages/index.tsx:9:27 - error TS2322: Type 'number' is not assignable to type 'void | Destructor'.
9 React.useEffect(() => 1)
Both npm run lint
and npm run type-check
are automatically run by npm run build
.
Lint is enabled only on pages/
, components/
and lib/
by default
As mentioned at: https://nextjs.org/docs/basic-features/eslint#linting-custom-directories-and-files
To enable it everywhere in the projects:
module.exports = {
eslint: {
dirs: ['.'],
},
}
Upvotes: 1
Reputation: 1616
you need to install required npm modules.
with Npm:
npm i -D babel-eslint eslint-config-airbnb eslint eslint-plugin-jsx-a11y eslint-plugin-import eslint-plugin-react eslint-plugin-react-hooks
with Yarn:
yarn add -D babel-eslint eslint-config-airbnb eslint eslint-plugin-jsx-a11y eslint-plugin-import eslint-plugin-react eslint-plugin-react-hooks
Here is related article about that
https://medium.com/@melih193/next-js-eslint-setup-tutorial-for-airbnb-config-c2b04183a92a
Upvotes: 15