microsoft/vscode-eslint

ESLint config in a lerna subpackage is not loaded correctly

janbiasi opened this issue ยท 14 comments

We currently have a problem with the eslint extension in combination with a lerna setup and multiple configuration files. The described issue occurs in a commercial project for a big company with closed source, so we can not add logs or traces to this issue - but we'll describe the error case as good as possible.

The Problem

ESLint in the VSCode (IDE only) will show errors for the import/resolver section inside the subpackage for the main application and it looks like that the ESLint extension is not reading the overwritten configuration file from the subpackage and is using the root .eslintrc.js.

Error case e.g. /packages/apps/main-app/src/ComponentXY.js

import OtherComponent from 'src/OtherComponent';
// => ESLint: unable to resolve path to 'src/OtherComponent'. (import/no-unresolved)

If we run the DEBUG=eslint-plugin-import:* ./node_modules/.bin/eslint --fix command on the project level we'll receive all errors displayed in the IDE that ESLint is not able to resolve the references to the components with absolute path. But if we run the exact same command inside our subpackage (/packages/apps/main-app/) we don't get any error about resolving modules.

So we assume that this is an issue with the VSCode ESLint extension because this behaviour only appears inside the IDE.

As temporary solution we switched our whole team to Atom because there is no issue with the ESLint integration. We're looking forward to get a solution for this weird behaviour.

Project information

The project uses the lerna structure with the folder packages, in this folder we have a wrapper folder for all apps of our customer called apps. Inside the apps we have main-app project and an additional .eslintrc.js configuration which will add the capability to resolve modules without the relative paths (e.g. src/Component instead of ../src/Component).

Our project structure

project/ (lerna root)
  + configs/
  |       + eslint-config/
  |             + node.js
  |
  + packages/
  |       + apps/ (lerna package)
  |        |    + main-app (lerna subpackage)
  |        |     |       + src/
  |        |     |       |    + Component.js
  |        |     |       | 
  |        |     |       + .eslintrc.js (app config)
  |        |     |       + package.json
  |        |
  |       + common/
  |
  + .eslintrc.js (root config, will use configs/eslint-config/node.js)
  + package.json
configs/eslint-config/node.js (root .eslintrc.js)
module.exports = {
	extends: [
		'@namics/eslint-config/configurations/es6-node.js',
		'@namics/eslint-config/configurations/es6-node-disable-styles.js',
	].map(require.resolve),
	globals: {
		__dirname: true,
	},
};
packages/apps/main-app/.eslintrc.js
const config = require('@configs/eslint-config/index');

module.exports = Object.assign(config, {
	settings: {
		'import/resolver': {
			node: {
				paths: ['src'],
			},
		},
	},
});
lerna.json
{
    "lerna": "2.0.0",
    "version": "independent",
    "packages": ["configs/*", "packages/*/*"]
}

General information

  • OS: MacOS High Sierra 10.13.2
  • Node: 6.12.3
  • Lerna: 2.0.0
  • VSCode: 1.22.2 (1.22.2)
    • ESLint Plugin: 1.4.8

Thanks for the detailed issue report. Looking at your project structure I think you need to configure proper working directories for the ESLint extension. See here for how to do this: https://github.com/Microsoft/vscode-eslint. The setting is: eslint.workingDirectories. In our case the working directory is very likely packages/app/main-app. If you don't set this the workingDirectory for eslint will be the project directory which makes the relative import src/.... not resolve correctly.

If this doesn't help would you be able to distill a small example and create a GitHub repository for it which I can clone. This would definitely ease tracking this down.

Thanks for the hint @dbaeumer but it looks like that this setting doesn't work properly in our case (added to the workspace settings and reloaded the editor). I'll try to create an example project setup as GitHub repository until the beginning of the next week. ๐Ÿ˜ƒ

Great. Ping me when available.

Hey @dbaeumer, example project is ready under janbiasi/vscode-eslint-issue-455, hit me up if you need more information.

@janbiasi thanks for the GitHub repository. This is definitely a setup issue. Executing .\node_modules\.bin\eslint .\packages\apps\main-app\src\components\AB.js reports the same set of problems.

capture

Executing eslint from packages\apps\main-app does not report any issues.

Using the following setting

	"eslint.workingDirectories": [
		{
			"directory": "packages/apps/main-app",
			"changeProcessCWD": true
		}
	]

Makes eslint work.

I will add something to the doc about changeProcessCWD which is indeed missing. I added that especially to resolve relative imports.

Thank you @dbaeumer, this fixed our issue! Also a huge thanks for the super-fast service ๐Ÿ˜ƒ

I'm running into the same issue but the setting doesn't seem to help.

From /project/web I can run node -r babel-register ./node_modules/.bin/eslint --ext .js src without any error. Webpack is able to compile my project normally and run in the browser.

In /project/.vscode/settings.json I have the following:

  "eslint.nodePath": "/Users/michaeldepetrillo/.nvm/versions/node/v8.11.1/bin/node -r babel-register",
  "eslint.packageManager": "yarn",
  "eslint.run": "onSave",
  "eslint.workingDirectories": [
	{
		"directory": "web",
		"changeProcessCWD": true
	}
  ],

Yet vscode is still reporting eslint errors. example

I have one config file located at /project/web/.eslintrc.yml. Any clue what might be going on?

@klassicd this is a different problem than reported by @janbiasi. It is complaining about import being a unexpected token.

I know to little about webpack and how ESLint is integrated into web pack. What happens if you run ESLint in the terminal outside of web pack. Will this work?

@dbaeumer Thanks, I think I figured out the issue.

My webpack config is written using babel.

So in /Workspace/project/web/.eslintrc.yml I have:

settings:
  import/resolver:
    webpack:
      config: tooling/webpack/config.js

To run test I have to include babel-register to parse the config file properly.

Works

$ pwd
$ /Workspace/project/web
$ node -r babel-register  ./node_modules/.bin/eslint --ext .js src

Fails

$ pwd
$ /Workspace/project/web
$ ./node_modules/.bin/eslint --ext .js src
Unexpected token import
/Workspace/project/web/tooling/webpack/config.js:5
import PATHS from './paths';
^^^^^^

My though was that the nodePath setting would be prepended to the eslint call. Any idea how I could accomplish this without rewriting the webpack config?

"eslint.nodePath": "/Users/michaeldepetrillo/.nvm/versions/node/v8.11.1/bin/node -r babel-register",

nodePath puts it onto the path but doesn't load the module. -r loads it. If we want to support this we need to have an option inside the eslint extension since it spawns the node process. But we should track this in a new issue. Do you want to look into this?

@dbaeumer Sure. If I understand correctly, we need to add a config option that allows an additional argument passed to the child process execArgv here? https://github.com/klassicd/vscode-languageserver-node/blob/master/server/src/files.ts#L152

Yes, that is correct. But the actual options needs to be defined in ESlint. So we need changes here and in the vscode-languageserver-node