eslint-plugin-import
eslint-plugin-import copied to clipboard
Webpack resolver looks for custom webpack config in packages with jsnext:main
With a .eslintrc like
"settings": {
"import/resolver": {
"webpack": {
"config": "webpack.karma.config.js"
}
}
},
when I import
import {takeEvery} from 'redux-saga';
I get the error
Cannot find module '/path/to/project/node_modules/redux-saga/webpack.karma.config.js
When I remove the jsnext:main entry from the package.json inside node_modules/redux-saga, the error goes away. So I guess the plugin is somehow trying to find a Webpack config inside redux-saga to load resolve configuration for ES6 files? This might be fine, looking for my custom Webpack config does not make sense, though.
Did you tried ./webpack.karma.config.js?
@k15a Prefixing the path with ./ does not change anything.
I'm using semantic-ui-react and encountered the exact same issue. https://github.com/Semantic-Org/Semantic-UI-React/commit/1911865b60230eb10e3834dd3e2a95ed9a69695b
Can corroborate. Our workaround was to create a symlink with the default name that targets the desired custom config, e.g.,
webpack.config.js -> karma.webpack.config.js
I found a workaround for this problem by converting my ".eslintrc" into a ".eslintrc.js" and use path.resolve as follow:
var path = require('path');
module.exports = {
settings: {
'import/resolver': {
webpack: {
config: path.resolve("./webpack.config.dev.js")
}
}
},
@gwleclerc Tried your suggestion and didn't work for me
Same issue here when using react-phone-number-input.
Perhaps this can be solved by mutating the configuration when the plugin first gets it, converting relative paths to absolute paths.
Ideally, it would do the conversion using the absolute path of the configuration file.
I tried putting the following line at https://github.com/benmosher/eslint-plugin-import/blob/master/resolvers/webpack/index.js#L65:
if (configPath !== settings.config) settings.config = configPath
however, while that fixes CLI usage, it doesn't fix it in the editor. The problem is that there are many invocations, each having to do fix-up on first invacation, and somehow in my editor the node_module is the first invocation.
I may have jumped the gun a bit with the PR above (variable names are confusing!)...
So my next question becomes, why is eslint trying to resolve those files anyway when (by default) it should ignore any files in node_modules?
By logging out the source and file passed into the resolver, I can see that it is attempting to resolve imports from within files in node_modules:
// Just showing the last two logs before the error
{ file: 'my-project/src/store/modules/index.js',
source: 'react-router-redux' }
{ file: '/my-project/node_modules/react-router-redux/es/index.js',
source: './reducer' }
eslint-plugin-import most definitely does not ignore files in node_modules, because it's trying to verify the exports that you're importing from there. Separately, webpack may alias some of those out, so the resolver needs to run on them.
Ah, I see. So would a valid fix for this issue be to simply check if we're in a node_module, and if so, ignore the configPath setting?
I think it's fair to say that when setting a configPath, you only want it to apply to your code, not any dependencies, right?
Although I guess that would lead to inconsistent behaviour between absolute paths and relative, where absolute paths would always resolve a webpack config, relative ones would not in this case...
If you agree with my previous comment, would you also agree that it should apply to all cases (that is, if we're in a dependency; ignore configPath)?
If it helps I'm also seeing this issue - there's a simple repository here showing the error:
https://github.com/cjpete/redux-saga-import-issue
@Billy- wouldnt this proposed solution work in clean manner?
Perhaps this can be solved by mutating the configuration when the plugin first gets it, converting relative paths to absolute paths.
I've successfully narrowed down the problem (at least for redux-saga) to the reexports being used:
export { foo } from './internal';
It seems that this plugin follows them, tries to resolve ./internal, but to resolve it it tries to apply a webpack config rules. It tries to resolve a webpack config, but to find it it uses a relative path and since it's looking at a package in node_modules we have a problem.
On the other hand 'manual' reexports are treated as safe:
import { foo } from './internal';
export { foo }
and it doesn't try to dive into ./internal in such case.
I'd still advocate for the simplest solution - just resolve config path once to an absolute path and be done with it, WDYT @ljharb ?
I’m not sure i know enough about it to decide - i prefer to avoid webpack aliasing, personally.
It’s certainly worth a PR if tests can be made to pass.
@Andarist I suppose yes it works, although as mentioned there is a caveat in that if the first file to be resolved is a node_module it doesn't work. I also think that mutating in this way is a bit of an antipattern..
wouldnt this proposed solution work in clean manner?
per discussion in #995: need to enhance resolver spec to include the linting file in order to properly load webpack config relative to the linting file and not deep imports
@gwleclerc your workaround works for me :) Had a yaml before, changed to .eslintrc.js with usage of path module and it worked.