eslint: Bug: [flat config] `.mjs` extension for config file

Environment

Environment Info:

Node version: v19.1.0 npm version: v8.19.3 Local ESLint version: v8.28.0 (Currently used) Global ESLint version: Not found Operating System: darwin 22.1.0

What parser are you using?

Default (Espree)

What did you do?

My npm package is commonjs, with .js extensions, alongside ESM with .mjs extensions for running tests. Running npx eslint . results in Node failing to parse the configuration file, as it assumes it to be commonjs.

What did you expect to happen?

The config file should only support a .mjs extension (eslint.config.mjs) to avoid this problem since Node will always execute it as ESM regardless of the type field defined in package.json.

What actually happened?

(Shortened)

Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
...
eslint.config.js:1
export default [
^^^^^^

SyntaxError: Unexpected token 'export'

Participation

  • I am willing to submit a pull request for this issue.

Additional comments

No response

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 7
  • Comments: 31 (18 by maintainers)

Commits related to this issue

Most upvoted comments

If your project does not have a package type field of "module", and your ESM is in .mjs files because .js is in CJS mode, and if you need to use a pure ESM dev dependency within the project ESLint config file, you are screwed. The eslint.config.js file is in CJS mode, meaning you can’t require the ESM dev dependency. ESLint must add support for eslint.config.mjs files.

If in the future ESLint decides to support only one config file name and format that any project could use, it would be eslint.config.mjs because that will always work as ESM no matter what the package type field is configured to, and the ESM format is capable of importing from both ESM as well as CJS dev dependencies.

The deprecation of .eslint* is a significant step forward.

However, maintaining support for eslint.config.js|cjs|mjs probably generates the least surprise for developers because that’s how npm packages are intended to work.

The flexibility to use cjs or mjs is huge when converting repos from one type to another or sharing configurations between repos. It allows for example to tackle tech debt in small steps and move faster.

In the 2022-12-01 TSC Meeting, we decided not to support .cjs and .mjs config files.

I’ve opened https://github.com/eslint/eslint/issues/16864 to discuss async function configs as a way to address https://github.com/eslint/eslint/issues/16580#issuecomment-1332817365.

Marking this issue as accepted to update Configuration Files (New) docs with the CJS config format for eslint.config.js files. I think we should add a note and one example.

fwiw the arguments against it are incredibly weak.

  • people won’t write CJS for much longer
    • we can only hope this is the case, but clearly this is speculation
    • most likely we’ll see CJS projects around for some years yet. many projects haven’t yet migrated, many which have plugin systems still require CJS plugins and don’t yet support ESM plugins
  • we don’t want config explosion again
    • supporting CJS/MJS is far from the spaghetti you had in the old config system. as already pointed out to you, node itself follows this exact convention (.cjs, .mjs to distinguish a module type which isn’t the one specified in your package manifest)
    • many widely used tools in the ecosystem already implement this exact same strategy (e.g. rollup)

as specified in the docs: https://nodejs.org/docs/latest-v14.x/api/packages.html#packages_determining_module_system

so @nzakas you’re worried implementing the same strategy as everyone else (incl node itself) will lead to the convoluted mess you had before. that’ll only happen if you decide to build your own strategy on top of it, which you 100% shouldn’t do (a team has already gone to a lot of effort to create this well defined strategy, just use it as-is).

not to sound harsh but you’re now the odd one out (eslint). all the other tools are already following the right strategy or have plans to.

edit:

some quick googling of what already follows this strategy:

  • rollup
  • webpack
  • web-test-runner
  • prettier
  • vite

@dburles you’ll need to use the environment variable to force the file to be interpreted as flat config.

Whoops! that does it, thanks. That’s a decent workaround.

@dburles you’ll need to use the environment variable to force the file to be interpreted as flat config.