Yarn 2 / Webpack require.resolve "use" array of UseEntry fails to reference loader

794 Views Asked by At

I'm trying to upgrade to yarn 2, and am running into a bit of a road block when it comes to "using" array based loaders and resolving properly.

Here is an excerpt from the previous working webpack configuration.

...
{
  test: /\.(gif|png|jpeg|jpg|svg)$/i,
  include: path.resolve(__dirname, "./static/images"),
  use: [
   "file-loader",
   {
     loader: "image-webpack-loader",
     options: {
       mozjpeg: { progressive: true },
       gifsicle: { interlaced: true },
       optipng: { enabled: false },
       pngquant: { enabled: false }
     }
   }
 ]
},
...

Running yarn dlx @yarnpkg/doctor returns the following error message.

assets/webpack.common.js:33:14: Webpack configs from non-private packages should avoid referencing loaders without require.resolve

Line 33 column 14 is the opening bracket character for the 'use' key.

When I wrap the loader strings in a require.resolve(...) I get the same error from the yarn doctor command.

Does anyone have an idea why there is an issue resolving here? This should be completely fine based on the docs from webpack but I'm not certain which tool is having difficulty here.

https://webpack.js.org/configuration/module/#ruleuse

Environment: OSX: 10.15.7 (19H15) - Catalina

node -v: v15.3.0

yarn --version: 2.4.0

webpack: ~5.9.0

1

There are 1 best solutions below

0
On

It is a bug in the @yarnpkg/doctor, the bug is located at this code block: https://github.com/yarnpkg/berry/blob/6b9df772ac785f73e6d08f0fc8c3f1718f296671/packages/yarnpkg-doctor/sources/cli.ts#L157-L159

if (name === `use` || name === `loader`) {
  checkForUnsafeWebpackLoaderAccess(workspace, property.initializer, {configuration, report});
}

The code block above treats the values for properties use and loader as a reference to the loader, but it does not handle arrays, in your case use is an array.

The first naive shot to fix this inside the @yarnpkg/doctor is to change the block above to:

if (name === `use` || name === `loader`) {
  if (property.initializer.kind === ts.SyntaxKind.ArrayLiteralExpression) {
    ts.forEachChild(property.initializer, childNode => {
    if (childNode.kind !== ts.SyntaxKind.ObjectLiteralExpression) {
        checkForUnsafeWebpackLoaderAccess(workspace, childNode, {configuration, report});
      }
    });
  } else {
    checkForUnsafeWebpackLoaderAccess(workspace, property.initializer, {configuration, report});
  }
}

The way this code block above handles array for loader and use properties is by visiting items and running doctor checks on each item which is not an object literal, object literals will be handled during recursion in processNode function. This special branch off for arrays is needed to treat non-object literal array items in a special way - as a loader references.

This is just one way how it can be implemented, another possible way is to remember that we are iterating inside loader and use arrays in processFile outer function local variables.