Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

next-lint Doesn't Support ESLint 9 #64409

Open
Tracked by #12 ...
dylandignan opened this issue Apr 12, 2024 · 76 comments
Open
Tracked by #12 ...

next-lint Doesn't Support ESLint 9 #64409

dylandignan opened this issue Apr 12, 2024 · 76 comments
Labels
bug Issue was opened via the bug report template. linear: next Confirmed issue that is tracked by the Next.js team. Linting Related to `next lint` or ESLint with Next.js.

Comments

@dylandignan
Copy link

dylandignan commented Apr 12, 2024

Link to the code that reproduces this issue

https://codesandbox.io/p/devbox/vigilant-pine-6wmz8y

To Reproduce

  1. Add next lint script to package.json per https://nextjs.org/docs/app/building-your-application/configuring/eslint
  2. Add .eslintrc.json to project per https://nextjs.org/docs/app/building-your-application/configuring/eslint
{
  "extends": "next/core-web-vitals"
}
  1. Run lint and get an error
➜  /workspace git:(master) ✗ npm run lint

> lint
> next lint

Invalid Options:
- Unknown options: useEslintrc, extensions, resolvePluginsRelativeTo, rulePaths, ignorePath, reportUnusedDisableDirectives
- 'extensions' has been removed.
- 'resolvePluginsRelativeTo' has been removed.
- 'ignorePath' has been removed.
- 'rulePaths' has been removed. Please define your rules using plugins.
- 'reportUnusedDisableDirectives' has been removed. Please use the 'overrideConfig.linterOptions.reportUnusedDisableDirectives' option instead.

Current vs. Expected behavior

Expected lint to run successfully, but it failed with errors.

Provide environment information

Operating System:
  Platform: linux
  Arch: x64
  Version: #1 SMP PREEMPT_DYNAMIC Sun Aug  6 20:05:33 UTC 2023
  Available memory (MB): 4102
  Available CPU cores: 2
Binaries:
  Node: 20.9.0
  npm: 9.8.1
  Yarn: 1.22.19
  pnpm: 8.10.2
Relevant Packages:
  next: 14.2.1-canary.0 // Latest available version is detected (14.2.1-canary.0).
  eslint-config-next: 14.1.4
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.1.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

ESLint (eslint-config-next)

Which stage(s) are affected? (Select all that apply)

next dev (local), next build (local), next start (local)

Additional context

It looks like this is coming from https://github.com/vercel/next.js/blob/canary/packages/next/src/cli/next-lint.ts. This needs to be changed to support ESLint 9's flat config https://eslint.org/docs/latest/use/migrate-to-9.0.0#flat-config. The migration guide is at https://eslint.org/docs/latest/use/configure/migration-guide

NEXT-3112

@dylandignan dylandignan added the bug Issue was opened via the bug report template. label Apr 12, 2024
@davidjulakidze
Copy link

davidjulakidze commented Apr 13, 2024

Bumping this for visibility, it does not seem to prevent build but unsure of the impact.

✓ Compiled successfully
   Linting and checking validity of types  .. 
⨯ ESLint: Invalid Options: - Unknown options: useEslintrc, extensions - 'extensions' has been removed.
✓ Linting and checking validity of type
"next": "^14.2.0",
"eslint-config-next": "^14.2.0",
"eslint": "^9.0.0",
{
  "extends": "next/core-web-vitals"
}

@elmarsto
Copy link

Bumping this, it is breaking package update automation at my corp

@GabenGar
Copy link
Contributor

GabenGar commented Apr 16, 2024

Yeah it's breaking change because ESLint 9.0.0 is a major release with a ton of breaking changes. You better hope NextJS didn't adhoc around every single ESLint implementation detail, so the migration to the newest version wouldn't take forever on their end.
For now a "fix" is to update next and eslint-config-next to 14.2.1 which limits the range of required ESLint version to eslint@"^7.23.0 || ^8.0.0" and therefore will crash on install/update instead.

@SukkaW
Copy link
Contributor

SukkaW commented Apr 17, 2024

IMHO, the adoption should be done gradually in the following steps:

  • Migrate eslint-config-next, so it exposes both the legacy eslintrc config and the new flat config.
  • Change Next.js internal ESLint implementation, allows it to accept both the legacy config .eslintrc and the new flat config eslint.config.js.
  • Change next lint so that it can accept eslint.config.js
  • Change create-next-app built-in template to use eslint.config.js
  • Change Next.js example to use eslint.config.js

@BnAmN
Copy link

BnAmN commented Apr 17, 2024

IMHO, the adoption should be done gradually in the following steps:

  • Migrate eslint-config-next, so it exposes both the legacy eslintrc config and the new flat config.

  • Change Next.js internal ESLint implementation, allows it to accept both the legacy config .eslintrc and the new flat config eslint.config.js.

  • Change next lint so that it can accept eslint.config.js

  • Change create-next-app built-in template to use eslint.config.js

  • Change Next.js example to use eslint.config.js

I would like to add that the new flat config file can have multiple names:

  • eslint.config.js
  • eslint.config.mjs
  • eslint.config.cjs

Source: https://eslint.org/docs/latest/use/configure/configuration-files#configuration-file

@JJozef
Copy link

JJozef commented Apr 21, 2024

Same error

image

package.json

"dependencies": {
    "next": "14.2.2"
},
"devDependencies": {
    "eslint": "^9.1.0",
    "eslint-config-next": "14.2.2"
}

.eslintrc.json

{
  "extends": ["next/core-web-vitals", "./node_modules/standard/eslintrc.json"],
  "rules": {
    "space-before-function-paren": "off"
  }
}

deploy

image

@Willem-Jaap
Copy link
Contributor

Not a fix but you can ignore eslint during build like so:

// next.config.js
module.exports = {
  eslint: {
    // Warning: This allows production builds to successfully complete even if
    // your project has ESLint errors.
    ignoreDuringBuilds: true,
  },
}

This way you have manual control over eslint, you can run a custom linting config before build.

@JJozef
Copy link

JJozef commented Apr 21, 2024

Not a fix but you can ignore eslint during build like so:

// next.config.js
module.exports = {
  eslint: {
    // Warning: This allows production builds to successfully complete even if
    // your project has ESLint errors.
    ignoreDuringBuilds: true,
  },
}

This way you have manual control over eslint, you can run a custom linting config before build.

I went back to version "eslint": "^8.41.0" and the error stopped.

@mirasayon
Copy link
Contributor

Same error

Screenshot 2024-04-22 204334

.eslintrc.json :
{ "extends": "next/core-web-vitals" }

I updated all the packages to the latest version but this still does not solve the problem

I don’t want to go back to the old version to fix it. If anyone knows how to solve the problem without going to the old version, please help me 🙏

@GabenGar
Copy link
Contributor

The only package update of relevance is eslint-config-next, which is tied to the version of next, aka wait for one of the newest nextjs versions. Until then you have to stick to old one.

@dalindev
Copy link

dalindev commented Apr 25, 2024

Same issue here, I thought I was crazy. Downgrade to an old version for now... 🤖 😸

devDependencies:
- eslint 9.1.1
+ eslint 8.57.0 (9.1.1 is available)

@sebalaini
Copy link

having the same problem here, I have a custom-shared lint config and my latest PR when linked locally to test it it fails, sebalaini/sebalaini-lints-config#6

@lebiosShred

This comment was marked as abuse.

@Systerr
Copy link

Systerr commented Sep 9, 2024

If only eslint-import is blocker right now then maybe its a good to consider use their fork https://github.com/un-ts/eslint-plugin-import-x ? Looks like it's a drop in replacement

@jamiter
Copy link

jamiter commented Sep 11, 2024

I've forced the usage of eslint-plugin-import-x by setting an override for eslint-config-next in my package.json:

{
  # ...
  "overrides": {
    "eslint-config-next": {
      "eslint": "$eslint", # this means using dependency's value
      "eslint-plugin-import": "npm:eslint-plugin-import-x@4.2.1"
    }
  }
}

This seems to work but I did have to disable a @next rule, because it isn't compatible with eslint@9:

'@next/next/no-duplicate-head': 'off',

I'm curious if is this works for everyone!

@AlbinoGeek
Copy link

If anyone else is tired of waiting, you also have the option of using SonarLint. I know, it sounds crazy, but even the free edition has better NextJS rules than Vercel's own ESLint rules/plugins. Better yet, it lets you disable the server-side ones using a group rule, if you don't want to be screamed at by impossible next/image recommendations, when you're really an SPA without the nextjs server bloat.

I stumbled upon this "solution" for the few projects we have that are forced to stick with Next, since they're too old to migrate. The only downside is 600MB RAM usage on the vscode plugin. Otherwise, integrates 1-to-1 with yarn scripts, vscode, and even next's build process. Was a free drop-in replacement.

@AlbinoGeek
Copy link

I'm curious if is this works for everyone!

Tried this, but also had to delete the compat for import which threw errors, then couldn't get past the part where @next/next/no-duplicate-head threw errors. No matter where I tried to disable the rule, yarn eslint ., yarn lint . eslint . etc all still threw errors parsing that rule. Moved to SolarLint instead.

@ldeveber
Copy link

ldeveber commented Sep 13, 2024

Hi everyone,

Unfortunately, we were not able to ship this with Next.js 15. The current understanding of this is that we cannot do a clean ship of this until certain plugins add support for ESLint v9. For example:

We will share updates as they come!

Question on import plugin, but it looks like they released support two weeks ago, but through a different PR?

sources:

Is there more that is being waited on or was that the only thing that was needed?

EDIT: forgot link to PR 🤦🏻‍♀️

@controversial
Copy link
Contributor

@ldeveber that’s not correct; eslint-plugin-import has not released support for eslint v9

see import-js/eslint-plugin-import#2996

The PR you linked adds support for using flat config under eslint v8, which is not what this issue is about.

Quoting the first message in the PR you linked:

And just to be clear, this is only aiming to provide support for flat config (which is a separate issue than supporting eslint v9)

@takueof

This comment was marked as off-topic.

@lyleunderwood
Copy link

So, when will the ESLint v9.x migration be complete?

Nobody knows when or if this will happen. You have the following options right now:

  • Stay on eslint 8 and wait and see if support eventually rolls out (you should probably do this),
  • Try one of the various hacks mentioned above,
  • Migrate away from eslint and lose first-class support from next,
  • Live without linting (not the end of the world),
  • Fix it yourself and open a PR, or
  • Go sponsor the project, donate some money to try and help get the work done.

This is the nature of volunteer-operated FOSS. There is no guarantee, there is no obligation.

rant By choosing to use an open source project like next, you are assuming a certain amount of risk, and you are transitively assuming hidden risk from all the nested dependencies of such a project. The big lie you are told is that such frameworks abstract away all these problems, that you will never have to deal with them. But the truth is that if you can't deal with them, then using these dependencies is a bad choice for commercial production applications.

If you don't have your own mirroring npm registry setup, you're not ready to use FOSS in production. If you can't dig into the underlying source code and understand on at least a basic level what's going on, you're not ready to use FOSS in production. If you can't figure out your own workarounds to problems like the one described in this thread, you're not ready to use FOSS in production.

It really is disingenuous for organizations to represent projects like next as a batteries-included, comprehensive solution to your problem of building a website, but I also understand that that's the state of market competition. If any framework described on their marketing page what responsibilities users are actually taking on by building something on top of their code, everybody would be scared off toward something that hides those inevitable complexities from potential users.

@ldeveber
Copy link

ldeveber commented Sep 16, 2024

@ldeveber that’s not correct; eslint-plugin-import has not released support for eslint v9

see import-js/eslint-plugin-import#2996

The PR you linked adds support for using flat config under eslint v8, which is not what this issue is about.

Quoting the first message in the PR you linked:

And just to be clear, this is only aiming to provide support for flat config (which is a separate issue than supporting eslint v9)

Thank you, but my question still remains:

Is there more that is being waited on or was that the only thing that was needed?

Or more specifically, are there specific parts of 9 that are being waited on, or just allowing 9 as a dependency?

EDIT:
Additionally trying to understand, because the official eslint version 9 support tracking listed it as supported? They're tracking flat config as a second post, and since BOTH were updated it makes it seem like full support is there. So if that is wrong, I would like to provide them with what is missing to fix the listing as to not mislead others?

And just want to clarify that I'm looking for more details to help, not trying to harp on what you guys do!

@lyleunderwood
Copy link

lyleunderwood commented Sep 16, 2024

eslint/eslint#18391 does list import as having eslint 9 support, which seems to be incorrect. It was stated 6 days ago that eslint-plugin-import does not yet support eslint@9, and the peer dependency is still set to eslint@8.

If you look at the entries for import in each of those tracking tables, you'll see that they both point at the same issue, import-js/eslint-plugin-import#2556. The problem is that this issue is only to implement flat config support, so the table in eslint/eslint#18391 should really not list it. I suspect that both tables were updated to indicate success when the one linked issue was closed, and mistakenly so.

The issue for supporting eslint@9, the one that should be linked in that table, is import-js/eslint-plugin-import#2948 which has been locked.

Edit:
I left a comment over there to try and get the table corrected.

Double edit:
It's now been corrected. Also the maintainer of eslint-plugin-import +1'd my comment, which I'll take as double-confirmation that it is correct to say that it does not currently support eslint@9.

@simplenotezy
Copy link

@SalahAdDin @AlbinoGeek @DamienCassou there might be an easier migration path, I wrote a setup guide for Eslint 9 with Next.js, starting from a minimal app, this should probably scale to work with any project but please let me know if there is any issue, this is kind of a long read : Eslint 9 & Next.js — Setup Guide

TLDR;

  • You should install and override eslint 9 to avoid any issues on npm install
  • You should declare your own build and lint rules
  • You should opt-out of Next.js linting during build
  • You should migrate your .eslintrc.(js|json|yml) using ESlint's @eslint/migrate-config
  • You should patch problematic plugins using ESLint's fixupPluginRules

The resulting files should look something like this

package.json

{
...
  "scripts": {
    "dev": "next dev",
    "build": "npm run lint && next build",
    "start": "next start",
    "lint": "eslint ."
   },
  ...
  "devDependencies": {
    ...
    "eslint": "^9.8.0",
    ...
  },
  "overrides": {
    "eslint": "^9.8.0"
  }
}

next.config.mjs

/** @type {import('next').NextConfig} */
const nextConfig = {
  eslint: {
    ignoreDuringBuilds: true,
  },
};

export default nextConfig;

eslint.config.mjs

// @ts-check
import path from "node:path";
import { fileURLToPath } from "node:url";
import js from "@eslint/js";
import { FlatCompat } from "@eslint/eslintrc";
import { fixupPluginRules } from "@eslint/compat";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
  baseDirectory: __dirname,
  recommendedConfig: js.configs.recommended,
  allConfig: js.configs.all,
});

const pluginsToPatch = [
  "@next/next",
  // Other plugins to patch, example :
  // "react-hooks",
];

const compatConfig = [...compat.extends("next/core-web-vitals")];

const patchedConfig = compatConfig.map((entry) => {
  const plugins = entry.plugins;
  for (const key in plugins) {
    if (plugins.hasOwnProperty(key) && pluginsToPatch.includes(key)) {
      plugins[key] = fixupPluginRules(plugins[key]);
    }
  }
  return entry;
});

const config = [...patchedConfig, { ignores: [".next/*"] }];

export default config;

@SalahAdDin @AlbinoGeek @DamienCassou there might be an easier migration path, I wrote a setup guide for Eslint 9 with Next.js, starting from a minimal app, this should probably scale to work with any project but please let me know if there is any issue, this is kind of a long read : Eslint 9 & Next.js — Setup Guide

TLDR;

  • You should install and override eslint 9 to avoid any issues on npm install
  • You should declare your own build and lint rules
  • You should opt-out of Next.js linting during build
  • You should migrate your .eslintrc.(js|json|yml) using ESlint's @eslint/migrate-config
  • You should patch problematic plugins using ESLint's fixupPluginRules

The resulting files should look something like this

package.json

{
...
  "scripts": {
    "dev": "next dev",
    "build": "npm run lint && next build",
    "start": "next start",
    "lint": "eslint ."
   },
  ...
  "devDependencies": {
    ...
    "eslint": "^9.8.0",
    ...
  },
  "overrides": {
    "eslint": "^9.8.0"
  }
}

next.config.mjs

/** @type {import('next').NextConfig} */
const nextConfig = {
  eslint: {
    ignoreDuringBuilds: true,
  },
};

export default nextConfig;

eslint.config.mjs

// @ts-check
import path from "node:path";
import { fileURLToPath } from "node:url";
import js from "@eslint/js";
import { FlatCompat } from "@eslint/eslintrc";
import { fixupPluginRules } from "@eslint/compat";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
  baseDirectory: __dirname,
  recommendedConfig: js.configs.recommended,
  allConfig: js.configs.all,
});

const pluginsToPatch = [
  "@next/next",
  // Other plugins to patch, example :
  // "react-hooks",
];

const compatConfig = [...compat.extends("next/core-web-vitals")];

const patchedConfig = compatConfig.map((entry) => {
  const plugins = entry.plugins;
  for (const key in plugins) {
    if (plugins.hasOwnProperty(key) && pluginsToPatch.includes(key)) {
      plugins[key] = fixupPluginRules(plugins[key]);
    }
  }
  return entry;
});

const config = [...patchedConfig, { ignores: [".next/*"] }];

export default config;

I tried following your suggestions, however, when running "npm run lint", it seems as though the file is not read, because it asks me to setup eslint:

? How would you like to configure ESLint? https://nextjs.org/docs/basic-features/eslint
❯  Strict (recommended)
   Base
   Cancel

Did I miss a step?

@poksme
Copy link

poksme commented Sep 17, 2024

@simplenotezy

Make sure your replace the rule "lint": "next lint" in your package.json by your own linting strategy, probably "lint": "eslint ."

@simplenotezy
Copy link

@simplenotezy

Make sure your replace the rule "lint": "next lint" in your package.json by your own linting strategy, probably "lint": "eslint ."

Thanks. Found your blog article and found a similar instruction.

@philsherry
Copy link

@samcx I see it’s the same developer who’s responsible for all three of those. Has anyone from Vercel asked if he needs any help to get things across the line? It’s quite a burden for one person.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issue was opened via the bug report template. linear: next Confirmed issue that is tracked by the Next.js team. Linting Related to `next lint` or ESLint with Next.js.
Projects
None yet
Development

No branches or pull requests