Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webpack dynamic alias resolution

I'm looking for a way to pass in a function via the [email protected] config to help Webpack dynamically resolve an alias on compile-time. I have various third-party packages that import, for example, package-a/file-b. However, depending on which third party package is importing package-a, I want it to be resolved to a different version of package-a; although there will be a version of package-a in node_modules, the older versions won't be in node_modules but a different directory. Since these are third parties, I do not want to manually alter their code. The version to use in the respective package is in the path name and there is an arbitrary number of packages.

Because package-a is a private package, it's not on npm nor versioned via Github.

These two have helped me get closer to this but both answers seem outdated: - https://github.com/webpack/webpack/issues/110 - Is it possible to create custom resolver in webpack?

Here is what I have so far:

config.resolve.plugins = [{
    apply(resolver) {
        resolver.plugin('module', function(request, callback) {
            if (request.request.startsWith('package-a')) {
                this.doResolve(
                    'file',
                    Object.assign({
                        ...request,
                        request: request.request.replace(/^package-a/, `${__dirname}/versions/v2.2.0`) + '.js',
                        file: true,
                        resolved: true,
                    }),
                    null,
                    callback
                );

                return;
            }
            callback();
        });
    }
}];

While it properly builds, the problem with this is that it is still evaluating to the node_modules package-a -- so I guess the code isn't working at all.

like image 227
Hiroki Osame Avatar asked May 22 '18 12:05

Hiroki Osame


Video Answer


1 Answers

The problem could be related to __dirname, which may be the __dirname of the webpack.config.js file and not your library. try to console.log(__dirname) at the plugin and see if the path is correct. also, you don't need to add '.js'

this resolver plugin works for me on WebPack 4 (slightly modified, hope to have not broken anything while adapting):

    const path = require('path');

    var monorepoResolver = {
      apply(resolver) {
        resolver.plugin('module', function(request, callback) {
          if (request.path.startsWith('package-a') === -1)  {
              callback();
            } else 
            {
              this.doResolve(
                'resolve',
                {
                  ...request,
                  request: request.request.replace(/^package-a/, `${__dirname}/versions/v2.2.0`),
                },
                'Edev Resolver',
                callback
              );
            }
        });
      }
    };


    module.exports = (baseConfig, env, defaultConfig) => {

      defaultConfig.resolve.plugins = defaultConfig.resolve.plugins || [];
      defaultConfig.resolve.plugins.push(monorepoResolver);


      return defaultConfig
    }
like image 69
Nir O. Avatar answered Oct 27 '22 00:10

Nir O.