26

当需要模块时,我有自己的约定。例如require("./components/SettingsPanel");应该解决require("./components/SettingsPanel/SettingsPanel.js");

有没有办法创建这样的解析器?

4

2 回答 2

41

是的,这是可能的。为了避免歧义并更容易实现,我们将使用前缀哈希符号作为您的约定的标记:

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

然后将其添加到您的配置文件中(当然,您可以稍后对其进行重构):

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
      ]
    }
    // ...
};
于 2015-04-24T23:30:05.290 回答
13

创建了一个更新的示例以使用Webpack v4。故意不使用 ES6 语法来实现向后兼容性。如果你愿意,你可以把它变成一个类。

您可以在https://github.com/webpack/enhanced-resolve阅读有关解析器示例的更多信息。

感谢里卡多提供原始答案。

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()]
    }
};
于 2019-08-06T14:02:34.907 回答