I've got a project with a .pre-commit-config.yaml
that features, among other things, the official ESLint hook. It works perfectly when using the old-style .eslintrc.json
config, but replacing it with the new-style eslint.config.js
causes it to fail.
The hook config looks like this:
- repo: https://github.com/pre-commit/mirrors-eslint
rev: v8.51.0
hooks:
- id: eslint
types: [javascript]
additional_dependencies: [
'globals@13.21.0',
'eslint@8.51.0',
'@eslint/js',
'eslint-config-prettier@9.0.0'
]
Running pre-commit install-hooks
, ESLint itself and the listed dependencies are seemingly installed without errors (no ~/.cache/pre-commit/pre-commit.log
gets created). I don't have ESLint globally installed.
This is the old-style .eslintc.json
config with which everything works:
{
"env": {
"es2022": true,
"browser": true
},
"extends": [
"eslint:recommended",
"prettier"
],
"ignorePatterns": [
"project/static/htmx/**"
],
"parserOptions": {
"sourceType": "module"
},
"rules": {}
}
However, using this eslint.config.js
fails, even though it seems to be perfectly valid when comparing to new style config examples in the ESLint documentation:
import globals from "globals";
import js from "@eslint/js";
import eslintConfigPrettier from "eslint-config-prettier";
export default [
js.configs.recommended,
eslintConfigPrettier,
{
languageOptions: {
globals: {
...globals.browser,
},
sourceType: "module",
ecmaVersion: 2022,
},
},
{
ignores: ["project/static/htmx/**"],
},
];
This is the error when running pre-commit run --all-files
:
eslint...................................................................Failed
- hook id: eslint
- exit code: 2
Oops! Something went wrong! :(
ESLint: 8.51.0
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'globals' imported from /Users/jkl/Development/foobar/eslint.config.js
Did you mean to import globals/index.js?
at new NodeError (node:internal/errors:406:5)
at packageResolve (node:internal/modules/esm/resolve:789:9)
at moduleResolve (node:internal/modules/esm/resolve:838:20)
at defaultResolve (node:internal/modules/esm/resolve:1043:11)
at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:383:12)
at ModuleLoader.resolve (node:internal/modules/esm/loader:352:25)
at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:228:38)
at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:85:39)
at link (node:internal/modules/esm/module_job:84:36)
ERR_MODULE_NOT_FOUND
is equally raised for the other two imports if I move them to the first line, so it's not a globals
issue.
Despite me installing all the necessary dependencies for those three imports in eslint.config.js
to work in the documented way, they cannot be found. So something's off, and the fact that the hook works fine with the old-style config, without changing .pre-commit-config.yaml
at all, makes me think that either a) I'm missing some crucial bit of configuration, or b) the ESLint hook just plain doesn't support the new-style config for some reason, or c) ESLint itself has some sort of incompatibility with the combination of the new config and the way pre-commit installs it.
I'm not a NodeJS user in daily life, nor familiar with the pre-commit internal workings. I'm happy to debug further and post more info to help solve this, with some assistance on what to look for next.
Disclaimer: I'm not a Node/Javascript expert, so take with care.
Pre-commit configures NODE_PATH
to point to the node_modules directory where the additional dependencies are installed (similar to a virtual environment in Python). To the best of my knowledge, NODE_PATH
is recognised by CommonJS require
, but not by ESModule import
. To quote Node's docs:
NODE_PATH is not part of resolving import specifiers. Please use symlinks if this behavior is desired.
I found that converting from ESModules (eslint.config.mjs
) to CommonJS (eslint.config.cjs
) resolved the issue for me.