Migrating from eslint-loader to eslint-webpack-plugin

Laurie - Feb 25 '21 - - Dev Community

eslint-loader is deprecated. The replacement, is eslint-webpack-plugin.

The README gives helpful information, but in looking for a full post on migration I came up empty. So this is that post for anyone else!

Existing Example

The README example is great for switching from rule to plugin syntax. So this,

const config = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'eslint-loader',
        options: {
          // eslint options (if necessary)
        },
      },
    ],
  },
}
Enter fullscreen mode Exit fullscreen mode

Becomes this.

import ESLintPlugin from 'eslint-webpack-plugin')

const config = {
  plugins: [new ESLintPlugin(options)],
}
Enter fullscreen mode Exit fullscreen mode

But what happens with all those additional key-value pairs included in the original ruleset? They can't just be dropped, it changes the functionality.

Plugin Options

Depending on what configuration you were passing, you may have to make some slight tweaks. For example, I had the following.

const config = {
  module: {
    rules: [
      {
      enforce: `pre`,
      test: /\.jsx?$/,
      exclude: (modulePath: string): boolean =>
        modulePath.includes(VIRTUAL_MODULES_BASE_PATH) ||
        vendorRegex.test(modulePath),
      loader: 'eslint-loader',
      },
    ],
  },
}
Enter fullscreen mode Exit fullscreen mode

test takes a glob for files to run the loader against. There are a few options in eslint-webpack-plugin that provide the same functionality, I opted for extensions.

exclude still works but because plugins run against the entire chunk, whereas loaders run against single files, it's a bit different. Mainly, it takes an array of strings rather than a function. Note that it also defaults to /node_modules/.

Finally, there is enforce. I didn't find an options level equivalent for this. As it turns out, I was able to drop it in my implementation. However, I believe you can use a hook to execute the plugin at a specific point in the build process.

So my migrated config became this.

const options = {
    extensions: [`js`, `jsx`],
    exclude: [
      `/node_modules/`,
      `/bower_components/`,
       VIRTUAL_MODULES_BASE_PATH,
    ],
    ...eslintOptions, // these are the options we'd previously passed in
}

const config = {
   return new ESLintPlugin(options)
}
Enter fullscreen mode Exit fullscreen mode

And that should be it

I had to do a bit more to complete the migration in the existing codebase. If you'd like to see the code in the wild you can check out the PR. But hopefully, this helps someone else!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .