Breno Polanski
Breno Polanski

Reputation: 86

eslint loader (for webpack 2) - You may need an appropriate loader to handle this file type

I'm using eslint-loader (for webpack 2) in my application, and I have this error:

./src/index.js
Module parse failed: /home/brenopolanski/github/saiku/srep-ui/saiku-report-viewer-ui/node_modules/eslint-loader/index.js!/home/brenopolanski/github/saiku/srep-ui/saiku-report-viewer-ui/src/index.js Unexpected token (28:4)
You may need an appropriate loader to handle this file type.
| const renderApp = (NewRoot) => {
|   render(
|     <AppContainer>
|       <NewRoot />
|     </AppContainer>,
 @ multi react-hot-loader/patch webpack-dev-server/client?http://localhost:3000 webpack/hot/only-dev-server ./src/index

well... if I remove the eslint-loader in my webpack, my application work correctly, but I need the eslint-loader working in my webpack.

package.json

{
  "scripts": {
    "start": "webpack-dashboard -- node server.js",
    "build": "npm run clean && npm run build:webpack",
    "build:webpack": "cross-env NODE_ENV=production webpack --progress --config ./config/webpack.prod -p",
    "test": "jest --coverage",
    "test:watch": "npm run test -- --watch",
    "storybook": "start-storybook -p 6006 -c storybook",
    "build-storybook": "build-storybook -c storybook",
    "clean": "rimraf build"
  },
  "devDependencies": {
    "@kadira/storybook": "^2.35.3",
    "autoprefixer": "^6.7.2",
    "babel-core": "^6.22.1",
    "babel-eslint": "^7.1.1",
    "babel-jest": "^18.0.0",
    "babel-loader": "^6.2.10",
    "babel-preset-es2015": "^6.22.0",
    "babel-preset-react": "^6.22.0",
    "babel-preset-stage-0": "^6.22.0",
    "chai": "^3.5.0",
    "cross-env": "^3.1.4",
    "css-loader": "^0.26.1",
    "deepmerge": "^1.3.2",
    "eslint": "^3.15.0",
    "eslint-loader": "^1.6.1",
    "eslint-plugin-flowtype": "^2.30.0",
    "eslint-plugin-import": "^2.2.0",
    "eslint-plugin-jsx-a11y": "^4.0.0",
    "eslint-plugin-mocha": "^4.8.0",
    "eslint-plugin-react": "^6.9.0",
    "extract-text-webpack-plugin": "^1.0.1",
    "file-loader": "^0.10.0",
    "html-webpack-plugin": "^2.28.0",
    "jest-cli": "^18.1.0",
    "json-loader": "^0.5.4",
    "postcss-loader": "^1.2.2",
    "react-hot-loader": "^3.0.0-beta.6",
    "rimraf": "^2.5.4",
    "style-loader": "^0.13.1",
    "stylus": "^0.54.5",
    "stylus-loader": "^2.4.0",
    "svg-url-loader": "^2.0.1",
    "url-loader": "^0.5.7",
    "webpack": "^2.2.1",
    "webpack-dashboard": "^0.3.0",
    "webpack-dev-server": "^2.3.0",
    "webpack-merge": "^2.6.1"
  },
  "dependencies": {
    "axios": "^0.15.3",
    "bootstrap": "^3.3.7",
    "classnames": "^2.2.5",
    "font-awesome": "^4.7.0",
    "moment": "^2.17.1",
    "pdfjs-dist": "^1.7.246",
    "react": "^15.4.2",
    "react-bootstrap": "^0.30.7",
    "react-datepicker": "^0.40.0",
    "react-dom": "^15.4.2",
    "react-pdfjs": "^1.0.7",
    "react-prop-types": "^0.4.0",
    "react-redux": "^5.0.2",
    "react-router": "^3.0.2",
    "react-router-bootstrap": "^0.23.1",
    "react-router-redux": "^4.0.7",
    "redux": "^3.6.0"
  }
}

.babelrc

{
  "presets": ["es2015", "stage-0", "react"],
  "plugins": ["react-hot-loader/babel"]
}

webpack.core.js

'use strict';

const webpack = require('webpack');
const HtmlPlugin = require('html-webpack-plugin');
const autoprefixer = require('autoprefixer');
const path = require('path');

module.exports = {
  output: {
    path: path.join(__dirname, '../build'),
    filename: '[name]-[hash].js'
  },

  plugins: [
    new HtmlPlugin({
      title: 'Saiku Report Viewer',
      template: path.join(__dirname, '../src', 'html', 'template.html')
    }),
    new webpack.LoaderOptionsPlugin({
      options: {
        eslint: {
          configFile: path.join(__dirname, './eslint.core.js'),
          useEslintrc: false
        },
        postcss: () => {
          return [autoprefixer];
        }
      }
    })
  ],

  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        include: /src/,
        loader: 'eslint-loader'
      }
    ],
    loaders: [
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        include: /src/,
        loader: 'babel-loader'
      },
      {
        test: /\.styl$/,
        loaders: [
          'style-loader',
          'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',
          'postcss-loader',
          'stylus-loader'
        ]
      },
      {
        test: /\.json$/,
        loader: 'json-loader'
      },
      {
        test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url-loader',
        query: {
          limit: 10000,
          mimetype: 'application/font-woff'
        }
      },
      {
        test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url-loader',
        query: {
          limit: '10000',
          mimetype: 'application/octet-stream'
        }
      },
      {
        test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'file-loader'
      },
      {
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'svg-url-loader',
        query: {
          limit: '10000',
          mimetype: 'application/svg+xml'
        }
      },
      {
        test: /\.(png|jpg)$/,
        loader: 'url-loader',
        query: {
          limit: 8192
        }
      },
      {
        test: /\.ico(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url-loader'
      }
    ]
  },

  node: {
    dns: 'empty',
    net: 'empty',
    tls: 'empty'
  },

  resolve: {
    alias: {
      src: path.join(__dirname, '../src'),
      components: path.join(__dirname, '../src', 'components')
    }
  }
};

webpack.dev.js

'use strict';

const webpack = require('webpack');
const HtmlPlugin = require('html-webpack-plugin');
const DashboardPlugin = require('webpack-dashboard/plugin');
const path = require('path');
const merge = require('webpack-merge');
const core = require('./webpack.core');

module.exports = merge.smart(core, {
  devtool: 'source-map',

  entry: [
    'react-hot-loader/patch',
    'webpack-dev-server/client?http://localhost:3000',
    'webpack/hot/only-dev-server',
    path.join(__dirname, '../src', 'index')
  ],

  output: {
    publicPath: ''
  },

  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new DashboardPlugin(),
    new webpack.LoaderOptionsPlugin({
      options: {
        eslint: {
          configFile: path.join(__dirname, './eslint.dev.js')
        }
      }
    })
  ],

  module: {
    loaders: [
      {
        test: /\.css$/,
        include: /(node_modules|bower_components|src)/,
        loaders: [
          'style-loader',
          'css-loader'
        ]
      }
    ]
  }
});

src/index.js

import React from 'react';
import { render } from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import Root from './containers/Root';

import 'bootstrap/dist/css/bootstrap.min.css';
import 'font-awesome/css/font-awesome.min.css';
import './styl/saiku.styl';

const renderApp = (NewRoot) => {
  render(
    <AppContainer>
      <NewRoot />
    </AppContainer>,
    document.querySelector('[data-js="app"]')
  );
};

renderApp(Root);

if (module.hot) {
  module.hot.accept('./containers/Root', () => {
    const NewRoot = require('./containers/Root').default;
    renderApp(NewRoot);
  });
}

Upvotes: 2

Views: 3553

Answers (1)

Michael Jungo
Michael Jungo

Reputation: 32972

In your webpack.core.js you define both module.rules and module.loaders. Although the module.loaders is still valid, for compatibility reasons, Webpack seems to ignore it when module.rules is present.

To solve your problem you can simply put all loaders in module.rules. Since you're merging the two configs, you also have to update webpack.dev.js to use module.rules, which is also recommend by the official docs: https://webpack.js.org/guides/migrating/#module-loaders-is-now-module-rules.

webpack.core.js

'use strict';

const webpack = require('webpack');
const HtmlPlugin = require('html-webpack-plugin');
const autoprefixer = require('autoprefixer');
const path = require('path');

module.exports = {
  output: {
    path: path.join(__dirname, '../build'),
    filename: '[name]-[hash].js'
  },

  plugins: [
    new HtmlPlugin({
      title: 'Saiku Report Viewer',
      template: path.join(__dirname, './src', 'html', 'template.html')
    }),
    new webpack.LoaderOptionsPlugin({
      options: {
        eslint: {
          configFile: path.join(__dirname, './eslint.core.js'),
          useEslintrc: false
        },
        postcss: () => {
          return [autoprefixer];
        }
      }
    })
  ],

  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        include: /src/,
        loader: 'eslint-loader'
      },
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        include: /src/,
        loader: 'babel-loader'
      },
      {
        test: /\.styl$/,
        loaders: [
          'style-loader',
          'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',
          'postcss-loader',
          'stylus-loader'
        ]
      },
      {
        test: /\.json$/,
        loader: 'json-loader'
      },
      {
        test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url-loader',
        query: {
          limit: 10000,
          mimetype: 'application/font-woff'
        }
      },
      {
        test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url-loader',
        query: {
          limit: '10000',
          mimetype: 'application/octet-stream'
        }
      },
      {
        test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'file-loader'
      },
      {
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'svg-url-loader',
        query: {
          limit: '10000',
          mimetype: 'application/svg+xml'
        }
      },
      {
        test: /\.(png|jpg)$/,
        loader: 'url-loader',
        query: {
          limit: 8192
        }
      },
      {
        test: /\.ico(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url-loader'
      }
    ]
  },

  node: {
    dns: 'empty',
    net: 'empty',
    tls: 'empty'
  },

  resolve: {
    alias: {
      src: path.join(__dirname, './src'),
      components: path.join(__dirname, './src', 'components')
    }
  }
};

webpack.dev.js

'use strict';

const webpack = require('webpack');
const HtmlPlugin = require('html-webpack-plugin');
const DashboardPlugin = require('webpack-dashboard/plugin');
const path = require('path');
const merge = require('webpack-merge');
const core = require('./webpack.core');

module.exports = merge.smart(core, {
  devtool: 'source-map',

  entry: [
    'react-hot-loader/patch',
    'webpack-dev-server/client?http://localhost:3000',
    'webpack/hot/only-dev-server',
    path.join(__dirname, './src', 'index')
  ],

  output: {
    publicPath: ''
  },

  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new DashboardPlugin(),
    new webpack.LoaderOptionsPlugin({
      options: {
        eslint: {
          configFile: path.join(__dirname, './eslint.dev.js')
        }
      }
    })
  ],

  module: {
    rules: [
      {
        test: /\.css$/,
        include: /(node_modules|bower_components|src)/,
        use: [
          'style-loader',
          'css-loader'
        ]
      }
    ]
  }
});

Upvotes: 2

Related Questions