Closed ideal-life-generator closed 8 years ago
@asdine a better solution is to name your actual webpack config webpack.config.babel.js
and then webpack and eslint will do the babel transpilation for you.
@ljharb There are apps which do not use webpack.config.js
file; the config is built with a function as a part of the build pipeline, in the middle of the build process. @asdine's solution helps to provide eslint-plugin-import
's resolver with the webpack config file even if the way of obtaining a webpack config that is passed to the webpack compiler is different than just require('./webpack.config.js')
.
@sompylasar i'm confused; if the webpack config file is ES6, it should be named ".babel" and everything's automatic. if it's not ES6, it shouldn't need babel-register.
@ljharb Everything's automatic when everything is default. When you have a custom build pipeline, there may be no webpack config file at all, neither webpack.config.babel.js
nor webpack.config.js
.
I'm very confused what kind of custom build pipeline one would have that utilizes a webpack config, claims to not have a file at all, but then passes a file path to the eslint resolver config?
In other words, if there's no file, then there's nothing to require in https://github.com/benmosher/eslint-plugin-import/issues/352#issuecomment-291967058 - if there is a file, then you can name it .babel.js
to avoid needing babel-register
.
There is no other way to configure eslint resolver I know about than to pass the file path. If there is, please tell me. Anyway, for the text editor to use eslint, we have to have a eslintrc (luckily this can be in executable JavaScript, not just static JSON). That file path passed to eslint resolver config is not used by the build pipeline (except for linting), the webpack compiler is called as a function from the build pipeline, and a generated webpack config is passed there.
By the way, which module implements the magic .babel.js
handling? That's obviously not Node itself, so if my eslintrc is called from Atom Linter it won't have the necessary environment for the magic to happen.
That's webpack itself; I'd assume eslint would do it too.
npm install --save-dev eslint-import-resolver-webpack
- resolved the issue!
By the way, which module implements the magic .babel.js handling?
@sompylasar: the Webpack resolver does it to match Webpack proper (which also does it). so it ought to work in any ESLint integration environment.
@benmosher ESLint does not rely on Webpack, so does not Atom Linter, so when Atom Linter calls ESLint, there is no Webpack magic built in.
clarification: eslint-import-resolver-webpack
implements the aforementioned magic.
So: Atom Linter => ESlint => eslint-plugin-import => eslint-import-resolver-webpack => ✨magic✨
resolved by adding the webpack resolver plugin to the eslintrc config and CHANGING in the webpack config files require path in ES5 style.
// webpack.config.dev.js
const path = require('path'); // instead of import path from 'path'
// .eslintrc
"settings": {
"import/resolver": {
"webpack": {
"config": "webpack.config.dev.js"
}
}
}
// package.json
"eslint-import-resolver-webpack": "^0.8.2",
I might as well be wrong, but it should be possible to use ES6 syntax with Webpack configuration if you rename it to webpack.babel.js
. This should not throw any errors from configuration validation part of eslint's Webpack resolver.
@asdine your solution works! Thanks!
I'm running into this issue as well, but only when viewing files in Atom.
When I run node_modules/.bin/eslint src/js/app/modules/sectionsPage/containers/SectionTileContainer.js
, everything works fine. But in Atom I get import/no-unresolved
errors.
If I run DEBUG=eslint-plugin-import:* $(npm bin)/eslint src/js/app/modules/sectionsPage/containers/SectionTileContainer.js
I can see the import/resolve fail, but I don't understand why. This is my output (I cut off a bit at the end):
eslint-plugin-import:resolver:node Resolving: +0ms stores/AuthStore from: /Users/bramschulting/projects/web-client/src/js/app/modules/sectionsPage/containers/SectionTileContainer.js
eslint-plugin-import:resolver:node resolve threw error: +4ms Error: Cannot find module 'stores/AuthStore' from '/Users/bramschulting/projects/web-client/src/js/app/modules/sectionsPage/containers'
at Function.module.exports [as sync] (/Users/bramschulting/projects/web-client/node_modules/resolve/lib/sync.js:36:11)
at Object.exports.resolve (/Users/bramschulting/projects/web-client/node_modules/eslint-import-resolver-node/index.js:19:28)
at v2 (/Users/bramschulting/projects/web-client/node_modules/eslint-module-utils/resolve.js:79:23)
at withResolver (/Users/bramschulting/projects/web-client/node_modules/eslint-module-utils/resolve.js:84:16)
at fullResolve (/Users/bramschulting/projects/web-client/node_modules/eslint-module-utils/resolve.js:101:22)
at relative (/Users/bramschulting/projects/web-client/node_modules/eslint-module-utils/resolve.js:46:10)
at resolve (/Users/bramschulting/projects/web-client/node_modules/eslint-module-utils/resolve.js:172:12)
at checkSourceValue (/Users/bramschulting/projects/web-client/node_modules/eslint-plugin-import/lib/rules/no-unresolved.js:29:50)
at checkSourceValue (/Users/bramschulting/projects/web-client/node_modules/eslint-module-utils/moduleVisitor.js:29:5)
at EventEmitter.checkSource (/Users/bramschulting/projects/web-client/node_modules/eslint-module-utils/moduleVisitor.js:34:5)
eslint-plugin-import:resolver:webpack Config path from settings: /Users/bramschulting/projects/web-client/webpack.config.js +0ms
eslint-plugin-import:resolver:webpack Config path resolved to: /Users/bramschulting/projects/web-client/webpack.config.js +1ms
eslint-plugin-import:resolver:webpack Using config: { cache: true,
debug: true,
devtool: 'source-map',
resolve:
{ root: '/Users/bramschulting/projects/web-client',
extensions: [ '', '.js', '.jade' ],
modulesDirectories:
[ 'node_modules',
'src/js/app',
'src/js/vendor_modules',
'tests/mock' ],
alias:
{ environment: '/Users/bramschulting/projects/web-client/src/js/app/config/env/local.js',
byebye: '/Users/bramschulting/projects/web-client/src/js/app/libs/byebye/byebye.js',
q: '/Users/bramschulting/projects/web-client/src/js/app/libs/q.js',
templates: '/Users/bramschulting/projects/web-client/src/templates',
backbone: 'exoskeleton/exoskeleton',
'appboy-web-sdk': 'appboy-web-sdk/appboy.core.min.js',
'react/lib/ReactMount': 'react-dom/lib/ReactMount' } },
...
The line which failes is:
import AuthStore from 'stores/AuthStore';
But that is located in /Users/bramschulting/projects/web-client/src/js/app/stores/AuthStore.js
, so the webpack resolve config should be correct, right?
Does anyone have an idea what's going on? This issue is driving me nuts 🔩
@bramschulting If you look into the error stacktrace, it is coming from eslint-import-resolver-node, while you expect it to use eslint-import-resolver-webpack. Seems you have configured both, and node takes precedence over webpack.
@sompylasar Oh right, thanks! That's due to a config we're extending (airbnb). Is there a way to disable this? I can manually overwrite it, but I'd prefer to disable it (as it's redundant) or 'use' the webpack config for the node resolver. Is that possible?
@bramschulting
I use it this way in my .eslintrc.js
:
"settings": {
"import/ignore": [
"node_modules",
"\\.(scss|less|css)$",
],
"import/resolver": {
"node": {
"moduleDirectory": [
"./src/webapp",
"./src/api",
"./src/server",
"./src/common",
],
},
"webpack": {
"config": "./webpack/configForEslintImportResolver.js",
},
},
},
@sompylasar yeah I was thinking of this too. But the downside of this is that you still have to define the moduleDirectory
in two locations (in .eslintrc and your webpack config).
@bramschulting Right. Well, I didn't go extra mile here, but you can require that info from a separate JS file 1) from .eslintrc.js
to give the module roots to eslint-import-resolver-node and 2) from the webpack config for the eslint-import-resolver-webpack to give the module roots to it.
@sompylasar OK, I'm running into another issue 🙈 I'm getting errors when importing files that have an alias in my webpack config, because the node-resolver tries to resolve them first I think.
I've been looking at this module to figure out where the order is being determined, but I can't seem to find it. Could you give me some pointers? I'd like to make a PR which allows for setting the resolve order, maybe like this:
"import/resolver": {
"order": ["webpack", "node"],
"webpack": {
"config": "webpack/config.js"
}
}
That would fix all the problems I mentioned, right?
@bramschulting The order of iterating over the configured resolvers is defined by the Map
iteration order: https://github.com/benmosher/eslint-plugin-import/blob/dc3609f895f5ad390d88fd9925dce40960117930/utils/resolve.js#L92-L97
But from the code, the import/resolver
config could be an array:
https://github.com/benmosher/eslint-plugin-import/blob/dc3609f895f5ad390d88fd9925dce40960117930/utils/resolve.js#L117-L120
I assume it could look like this, but I haven't tested it:
"import/resolver": [
{
"webpack": {
"config": "./webpack/config.js"
}
},
{
"node": {
"moduleDirectory": [
"whatever"
]
}
}
]
I also recommend to write relative paths explicitly with ./
, to make them more visible (also someone reported that the path without ./
didn't work for them, but I doubt this is true).
The array shape of import/resolver
is not documented, by the way, but that is a documentation issue: https://github.com/benmosher/eslint-plugin-import/blob/ccd93942a0b9f59f1b698672ba167ece1aa9f5f1/README.md#resolvers
CC @benmosher
Just wanted to thank @sompylasar for his example of ignoring node_modules. That resolved an issue that broken eslint for us. Thank you!!
@gricard You're welcome!
as @arkaitzgarro said, it works for me.
but I didn't use path.
config: path.join(__dirname, 'webpack.config.js')
my .eslintrc.js :
module.exports = {
//... other configs
plugins: [
'vue',
'import'
],
settings: {
"import/resolver": {
"webpack": {
"config": "./build/webpack.base.conf.js"
}
}
},
}
files location:
|-- package.json
|-- .eslintrc.js
|-- build
|-- webpack.base.conf.js
MARK
What did it for me was to move extensions: ['*', '.js', '.jsx']
from module.rules[0].resolve
to the root resolve
field (in webpack.config.js
). .jsx
files were problematic.
Before:
resolve: {
alias: {
component: path.resolve(__dirname, 'frontend/component/'),
store: path.resolve(__dirname, 'frontend/store/'),
lib: path.resolve(__dirname, 'frontend/lib/'),
context: path.resolve(__dirname, 'frontend/context/'),
},
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: ['@babel/plugin-proposal-object-rest-spread'],
},
},
resolve: {
extensions: ['*', '.js', '.jsx'], // <-- This has to be moved up
},
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
},
After:
resolve: {
alias: {
component: path.resolve(__dirname, 'frontend/component/'),
store: path.resolve(__dirname, 'frontend/store/'),
lib: path.resolve(__dirname, 'frontend/lib/'),
context: path.resolve(__dirname, 'frontend/context/'),
},
extensions: ['*', '.js', '.jsx'], // <-- Here, it works
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: ['@babel/plugin-proposal-object-rest-spread'],
},
},
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
},
@arkaitzgarro
Thank you so much. You solved my one-year problem.
.eslintrc
webpack.config.js
src/index.js
in console: