Home > front end >  Is there any way to specify the target resolution for a specific dependency in webpack?
Is there any way to specify the target resolution for a specific dependency in webpack?

Time:06-23

Lets suppose our dependency has the following package.json described as:

{
  "name": "some-dependency",
  "exports": {
    ".": {
      "browser": {
        "import": "...",
        "require": "..."
      },
      "node": {
        "import": "...",
        "require": "..."
      },
    }
  }
}

How can I make webpack to resolve the node export individually only for some-dependency?. I've tried something like this:

module.exports = {

  // ...

  resolve: {

    extensions: [".jsx", ".js"],
    conditionNames: ["node", "some-dependency"],
  },
};

but it applies globally and doesn't seem to do the work right.

CodePudding user response:

The conditionNames property is not about priority order. It is about which fields to use. The priority order is determined by exports object key order.

Further, in your case, it is not possible to achieve this via any Webpack configuration. You will have to build your own plugin to add custom resolver logic using enhanced-resolver. For example:

const { readFileSync } = require('fs');
const path = require('path');

// The module for which you need custom resolution
const targetDependency = 'some-dependency';

class MyCustomResolver {
  constructor(source, target) {
    this.source = source;
    this.target = target;
  }

  apply(resolver) {
    const target = resolver.ensureHook(this.target);

    resolver
      .getHook(this.source)
      .tapAsync('MyCustomResolver', (request, resolveContext, callback) => {
        // Any logic you need to create a new `request` can go here
        let newRequest = { ...request };

        if (request.request === targetDependency) {
          // Modify your newRequest object here.
          // Step 1: Read package.json of `some-dependency`.
          const json = JSON.parse(readFileSync(`node_module/${targetDependency}/package.json`));

          // Step 2: Extract required object
          const node = json.exports['.'].node;

          // Step 3: Modify newRequest object (Example only)
          newRequest.request = path.join(__dirname, 'node_modules', node.require);

          // Step 4. Modify additional param of request object if any
        }

        // Call the resolution function.
        resolver.doResolve(target, newRequest, null, resolveContext, callback);
      });
  }
}

module.exports = {
  resolve: {
    plugins: [
      MyCustomResolver
    ]
  }
};
  • Related