Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to create custom resolver in webpack?

Tags:

webpack

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?

like image 809
Vitalii Korsakov Avatar asked Jan 19 '15 14:01

Vitalii Korsakov


People also ask

What is alias in webpack?

Aliasing is webpack's handy way to shave time and keystrokes off importing frequently used modules. You will need the path module, included with node. js, as it is how you will tell webpack where to look for those specific files. Using the resolve. alias property, you can define aliases for frequently imported modules.

What is enhanced resolve?

Similar to webpack , the core of enhanced-resolve functionality is implemented as individual plugins that are executed using tapable . These plugins can extend the functionality of the library, adding other ways for files/contexts to be resolved. A plugin should be a class (or its ES5 equivalent) with an apply method.

Does webpack include node_modules?

Webpack builds a dependency graph used internally Now all modules that are used in your app are included in the dependency graph. Your project have many installed dependencies in the node_modules folder that should not be included in your client-side JavaScript production bundle.


2 Answers

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
      ]
    }
    // ...
};
like image 127
Ricardo Stuven Avatar answered Oct 18 '22 03:10

Ricardo Stuven


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()]
    }
};
like image 34
jsonUK Avatar answered Oct 18 '22 04:10

jsonUK