remix icon indicating copy to clipboard operation
remix copied to clipboard

ESLint v9 doesn't work with .eslintrc.cjs config

Open anton-pas opened this issue 1 year ago • 5 comments

Reproduction

I've installed ESlint v9.12.0 and would like to update the old eslint config (.eslintrc.js file). It looks like this:

module.exports = {
	extends: [
		'@remix-run/eslint-config',
		'@remix-run/eslint-config/node',
		'@remix-run/eslint-config/jest-testing-library',
		'prettier',
	],
	ignorePatterns: [
		'**/*.test.ts',
		'**/*.test.js',
		'**/*.test.tsx',
		'**/*.test.jsx',
		'**/*.spec.ts',
		'**/*.spec.js',
		'**/*.spec.tsx',
		'**/*.spec.jsx',
	],
	settings: {
		jest: {
			version: 27,
		},
	},
	rules: {
		'react/display-name': 'off',
	},
};

So I wonder if there any examples of configs in a new format like eslint.config.js, eslint.config.mjs or eslint.config.cjs specifically for Remix framework.

I've seen this file - templates/remix/.eslintrc.cjs. Can it be considered as default eslint config for now?

System Info

System:
    OS: macOS 13.6.7
    CPU: (10) arm64 Apple M1 Pro
    Memory: 118.58 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.18.2 - ~/.nvm/versions/node/v18.18.2/bin/node
    npm: 9.8.1 - ~/.nvm/versions/node/v18.18.2/bin/npm
  Browsers:
    Safari: 18.0
  npmPackages:
    @remix-run/dev: 2.11.2 => 2.11.2

Used Package Manager

npm

Expected Behavior

A new eslint config is present for Eslint v9 (eslint.config.js, eslint.config.mjs or eslint.config.cjs)

Actual Behavior

Existing eslint config is not adapted to the latest version of ESlint

anton-pas avatar Oct 14 '24 11:10 anton-pas

As of Eslint v9 the old .eslintrc.js style config is deprecated and disabled by default. If you still want to use it you need to set a ESLINT_USE_FLAT_CONFIG env var to false. Source -> https://eslint.org/docs/latest/use/configure/configuration-files-deprecated

Since @remix-run/eslint-config uses the old eslintrc format, the config can't be reused in the new flat config format. The rules and settings are re-usable, but you'd need to import them directly and you'd also need to manually add the plugins.

Like this:

// eslint.config.mjs

import remixCore from '@remix-run/eslint-config/rules/core.js'
import remixImport from '@remix-run/eslint-config/rules/import.js'
import remixJsxA11y from '@remix-run/eslint-config/rules/jsx-a11y.js'
import remixReact from '@remix-run/eslint-config/rules/react.js'
import remixReactSettings from '@remix-run/eslint-config/settings/react.js'
import pluginImport from 'eslint-plugin-import'
import pluginJsxA11y from 'eslint-plugin-jsx-a11y'
import pluginReact from 'eslint-plugin-react'
import pluginReactHooks from 'eslint-plugin-react-hooks'

const config = [{
  settings: {
    ...remixReactSettings
  },
  plugins: {
    'jsx-a11y': pluginJsxA11y,
    import: pluginImport,
    react: pluginReact,
    'react-hooks': pluginReactHooks
  },
  rules: {
    ...remixCore,
    ...remixImport,
    ...remixReact,
    ...remixJsxA11y
  }
}]

export default config

Keep in mind this example doesn't take into account the overrides, globals, or ignored files used in @remix-run/eslint-config.

If it's cool with the Remix team I would be happy to dive into this further and open a PR to add a flat config alternative to @remix-run/eslint-config

HW13 avatar Oct 18 '24 21:10 HW13

@HW13 The team has deprecated @remix-run/eslint-config basically right after releasing Remix v2, hence the update to the separate configs in the templates in #7597

MichaelDeBoey avatar Oct 18 '24 23:10 MichaelDeBoey

Thanks @MichaelDeBoey, I was not aware of that - my bad 😅

Well, If you guys are interested in migrating the templates to the new flat config format I'd be happy to contribute!

HW13 avatar Oct 19 '24 00:10 HW13

@HW13 I'm currently working on doing exactly that: migrating the templates to the new flat config format

Once I have a PR, I'll link to this issue

MichaelDeBoey avatar Oct 19 '24 01:10 MichaelDeBoey

That's what I was able to configure, not sure that's 100% correct variant:

// eslint.config.mjs

/** @type {import('eslint').Linter.FlatConfig[]} */
import js from "@eslint/js";
import typescriptEslint from "@typescript-eslint/eslint-plugin";
import typescriptParser from "@typescript-eslint/parser";
import globals from "globals";
import importPlugin from "eslint-plugin-import";

import reactPlugin from "eslint-plugin-react";
import jsxA11yPlugin from "eslint-plugin-jsx-a11y";
import reactHooksPlugin from "eslint-plugin-react-hooks";

const __dirname = new URL(".", import.meta.url).pathname;

export default [
  js.configs.recommended,
  importPlugin.flatConfigs.recommended,
  {
    ignores: [
      "build/*",
      "build/**/*",
      "**/build/**/*",
      "eslint.config.mjs",
      "coverage/*",
      "coverage/**/*",
      "node_modules/*",
      "node_modules/**/*",
      "global.d.ts",
      "**/*.test.ts",
      "**/*.test.js",
      "**/*.test.tsx",
      "**/*.test.jsx",
      "**/*.spec.ts",
      "**/*.spec.js",
      "**/*.spec.tsx",
      "**/*.spec.jsx",
    ],
  },
  {
    files: ["**/*.{js,jsx,ts,tsx}"],
    languageOptions: {
      ecmaVersion: "latest",
      sourceType: "module",
      globals: {
        ...globals.browser,
        ...globals.commonjs,
        ...globals.es6,
        ...globals.jest,
        process: "readonly",
      },
    },
    plugins: {
      react: reactPlugin,
      "jsx-a11y": jsxA11yPlugin,
      "react-hooks": reactHooksPlugin,
    },
    rules: {
      ...reactHooksPlugin.configs.recommended.rules,
      ...reactPlugin.configs.recommended.rules,
      ...jsxA11yPlugin.configs.recommended.rules,
      "react/no-unescaped-entities": "off",
      "react/display-name": "off",
      "react/prop-types": "off",
      "no-prototype-builtins": "off",
    },
    settings: {
      react: {
        version: "detect",
      },
      jest: {
        version: 27,
      },
      formComponents: ["Form"],
      linkComponents: [
        { name: "Link", linkAttribute: "to" },
        { name: "NavLink", linkAttribute: "to" },
      ],
      "import/resolver": {
        typescript: {
          alwaysTryTypes: true,
          project: "./tsconfig.json",
        },
      },
      "import/ignore": [".(css)$"],
    },
  },
  // TypeScript configuration
  {
    files: ["**/*.{ts,tsx}"],
    languageOptions: {
      parser: typescriptParser,
      parserOptions: {
        tsconfigRootDir: __dirname,
        project: ["./tsconfig.json"],
      },
      globals: {
        ...globals.node,
        React: "readonly",
        NodeJS: "readonly",
      },
    },
    plugins: {
      "@typescript-eslint": typescriptEslint,
    },
    rules: {
      ...typescriptEslint.configs.recommended.rules,
      "@typescript-eslint/no-explicit-any": "off",
      "@typescript-eslint/no-require-imports": "off",
      "@typescript-eslint/no-empty-object-type": "off",
      "@typescript-eslint/ban-ts-comment": "off",
    },
  },
  // Node environment for eslint.config.mjs
  {
    files: ["eslint.config.mjs"],
    env: {
      node: true,
    },
  },
];

anton-pas avatar Oct 21 '24 10:10 anton-pas

I'm currently working on doing exactly that: migrating the templates to the new flat config format Once I have a PR, I'll link to this issue

@MichaelDeBoey Do you happen to have any updates on this?

kpalmvik avatar Jan 03 '25 10:01 kpalmvik

Thank you for opening this issue, and our apologies we haven't gotten around to it yet!

With the release of React Router v7 we are sun-setting continued development/maintenance on Remix v2. If you have not already upgraded to React Router v7, we recommend you do so. We've tried to make the upgrade process as smooth as possible with our Future Flags. We are now in the process of cleaning up outdated issues and pull requests to improve the overall hygiene of our repositories.

We plan to continue to address 2 types of issues in Remix v2:

  • Bugs that pose security concerns
  • Bugs that prevent upgrading to React Router v7

If you believe this issue meets one of those criteria, please respond or create a new issue.

For all other issues, ongoing maintenance will be happening in React Router v7, so:

  • If this is a bug, please reopen this issue in that repo with a new minimal reproduction against v7
  • If this is a feature request, please open a new Proposal Discussion in React Router, and if it gets enough community support it can be considered for implementation

If you have any questions you can always reach out on Discord. Thanks again for providing feedback and helping us make our framework even better!

github-actions[bot] avatar May 21 '25 18:05 github-actions[bot]