diff --git a/lib/NormalModule.js b/lib/NormalModule.js index fdabc3000ce..3e9dc55554a 100644 --- a/lib/NormalModule.js +++ b/lib/NormalModule.js @@ -184,6 +184,21 @@ class NormalModule extends Module { resolve(context, request, callback) { resolver.resolve({}, context, request, {}, callback); }, + getResolve(options) { + const child = options ? resolver.withOptions(options) : resolver; + return (context, request, callback) => { + if (callback) { + child.resolve({}, context, request, {}, callback); + } else { + return new Promise((resolve, reject) => { + child.resolve({}, context, request, {}, (err, result) => { + if (err) reject(err); + else resolve(result); + }); + }); + } + }; + }, emitFile: (name, content, sourceMap) => { if (!this.buildInfo.assets) { this.buildInfo.assets = Object.create(null); diff --git a/lib/ResolverFactory.js b/lib/ResolverFactory.js index 47028ee7ffe..80c5e8b685c 100644 --- a/lib/ResolverFactory.js +++ b/lib/ResolverFactory.js @@ -7,6 +7,8 @@ const { Tapable, HookMap, SyncHook, SyncWaterfallHook } = require("tapable"); const Factory = require("enhanced-resolve").ResolverFactory; +/** @typedef {import("enhanced-resolve").Resolver} Resolver */ + module.exports = class ResolverFactory extends Tapable { constructor() { super(); @@ -53,11 +55,22 @@ module.exports = class ResolverFactory extends Tapable { } _create(type, resolveOptions) { + const originalResolveOptions = Object.assign({}, resolveOptions); resolveOptions = this.hooks.resolveOptions.for(type).call(resolveOptions); const resolver = Factory.createResolver(resolveOptions); if (!resolver) { throw new Error("No resolver created"); } + /** @type {Map} */ + const childCache = new Map(); + resolver.withOptions = options => { + const cacheEntry = childCache.get(options); + if (cacheEntry !== undefined) return cacheEntry; + const mergedOptions = Object.assign({}, originalResolveOptions, options); + const resolver = this.get(type, mergedOptions); + childCache.set(options, resolver); + return resolver; + }; this.hooks.resolver.for(type).call(resolver, resolveOptions); return resolver; } diff --git a/test/cases/loaders/resolve/index.js b/test/cases/loaders/resolve/index.js new file mode 100644 index 00000000000..07e030a14e8 --- /dev/null +++ b/test/cases/loaders/resolve/index.js @@ -0,0 +1,7 @@ +it("should be possible to create resolver with different options", () => { + const result = require("./loader!"); + expect(result).toEqual({ + one: "index.js", + two: "index.xyz" + }); +}) diff --git a/test/cases/loaders/resolve/index.xyz b/test/cases/loaders/resolve/index.xyz new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/cases/loaders/resolve/loader.js b/test/cases/loaders/resolve/loader.js new file mode 100644 index 00000000000..eeee48bc7d0 --- /dev/null +++ b/test/cases/loaders/resolve/loader.js @@ -0,0 +1,11 @@ +const path = require("path"); +module.exports = async function() { + const resolve1 = this.getResolve(); + const resolve2 = this.getResolve({ + extensions: [".xyz", ".js"] + }); + return `module.exports = ${JSON.stringify({ + one: path.basename(await resolve1(__dirname, "./index")), + two: path.basename(await resolve2(__dirname, "./index")), + })}`; +};