29

I have my own convention when require modules. E.g. require("./components/SettingsPanel"); should be resolved to require("./components/SettingsPanel/SettingsPanel.js");

Is there any way to create such resolver?

Vitalii Korsakov
  • 45,737
  • 20
  • 72
  • 90

2 Answers2

43

Yes, it's possible. To avoid ambiguity and for easier implementation, we'll use a prefix hash symbol as marker of your convention:

require("#./components/SettingsPanel");

Then add this to your configuration file (of course, you can refactor it later):

var webpack = require('webpack');
var path = require('path');

var MyConventionResolver = {
  apply: function(resolver) {
    resolver.plugin('module', function(request, callback) {
      if (request.request[0] === '#') {
        var req = request.request.substr(1);
        var obj = {
          path: request.path,
          request: req + '/' + path.basename(req) + '.js',
          query: request.query,
          directory: request.directory
        };
        this.doResolve(['file'], obj, callback);
      }
      else {
        callback();
      }
    });
  }
};


module.exports = {
    resolve: {
      plugins: [
        MyConventionResolver
      ]
    }
    // ...
};
Mike Blandford
  • 3,952
  • 4
  • 29
  • 32
Ricardo Stuven
  • 4,704
  • 2
  • 34
  • 36
  • 3
    see also: https://github.com/webpack/docs/wiki/list-of-plugins#resolverplugin and https://github.com/webpack/webpack/blob/master/lib/ResolverPlugin.js#L13 – jantimon Dec 16 '15 at 07:20
  • This seems to process only files that do not have relative paths. As soon as I remove the # char the path is interpreted as relative and the resolver is bypassed. Is there any way to intercept relative paths and modify them? – Adrian Moisa Jun 12 '18 at 13:32
  • As stated, the # character is used just for this example implementation. You can use any other prefix character or no prefix at all, but in the latter case the convention will be applied to *all* required paths. – Ricardo Stuven Jun 12 '18 at 15:02
  • @AdrianMoisa to run the resolver on relative paths, you'd want to replace the string `module` with `normal`: https://webpack.js.org/api/resolvers/ – Andrew Sep 02 '18 at 17:26
  • 2
    Can you, please, provide link to documentation about what resolver.plugin and doResolve accept as parameters. I've tried but couldn't find it. This is not enough: https://webpack.js.org/api/resolvers/, and I'm not even sure it is the same thing. Seems there are no clear instructions on how to make this things other than digging through source code, which is not the quickest way to do things. – Marko Mar 01 '19 at 14:27
  • 3
    @Marko I'm searching this also. but until then, you can print the arguments variable – Stav Alfi Jun 29 '19 at 12:59
17

Created an updated example to work with Webpack v4. Purposely did not use ES6 syntax for backwards compatibility. You can make it a class if you wish.

You can read more about resolver examples at https://github.com/webpack/enhanced-resolve.

Thanks Ricardo for supplying the original answer.

var webpack = require('webpack');
var path = require('path');

function MyConventionResolver (source, target) {
    this.source = source || 'resolve';
    this.target = target || 'resolve';
}

MyConventionResolver.prototype.apply = function(resolver) {
    var target = resolver.ensureHook(this.target);
    resolver.getHook(this.source).tapAsync('MyConventionResolver', function(request, resolveContext, callback) {
        if (request.request[0] === '#') {
            var req = request.request.substr(1);
            var obj = Object.assign({}, request, {
                request: req + '/' + path.basename(req) + '.js',
            });
            return resolver.doResolve(target, obj, null, resolveContext, callback);
        }
        callback();
    });
}


// In your Webpack Config
module.exports = {
    ...
    resolve: {
        plugins: [new MyConventionResolver()]
    }
};
jsonUK
  • 345
  • 3
  • 9
  • 2
    Just FYI, webpack v4 [only supports](https://github.com/webpack/webpack/blob/webpack-4/package.json#L85) versions of node that [support class syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#Browser_compatibility) – Chris Deacy Dec 10 '19 at 21:07