improve merging of resolve and parsing options
by rules and via loader API Arrays overwrite by default, but can reference old value with "..."
这个提交包含在:
父节点
53a5ae2143
当前提交
b3ec775453
|
@ -17,7 +17,7 @@ const {
|
|||
const NormalModule = require("./NormalModule");
|
||||
const RawModule = require("./RawModule");
|
||||
const RuleSet = require("./RuleSet");
|
||||
const cachedMerge = require("./util/cachedMerge");
|
||||
const { cachedCleverMerge } = require("./util/cleverMerge");
|
||||
|
||||
const EMPTY_RESOLVE_OPTIONS = {};
|
||||
|
||||
|
@ -304,7 +304,7 @@ class NormalModuleFactory extends Tapable {
|
|||
typeof settings[r.type] === "object" &&
|
||||
settings[r.type] !== null
|
||||
) {
|
||||
settings[r.type] = cachedMerge(settings[r.type], r.value);
|
||||
settings[r.type] = cachedCleverMerge(settings[r.type], r.value);
|
||||
} else {
|
||||
settings[r.type] = r.value;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
const { Tapable, HookMap, SyncHook, SyncWaterfallHook } = require("tapable");
|
||||
const Factory = require("enhanced-resolve").ResolverFactory;
|
||||
const { cachedCleverMerge } = require("./util/cleverMerge");
|
||||
|
||||
/** @typedef {import("enhanced-resolve").Resolver} Resolver */
|
||||
|
||||
|
@ -66,7 +67,7 @@ module.exports = class ResolverFactory extends Tapable {
|
|||
resolver.withOptions = options => {
|
||||
const cacheEntry = childCache.get(options);
|
||||
if (cacheEntry !== undefined) return cacheEntry;
|
||||
const mergedOptions = Object.assign({}, originalResolveOptions, options);
|
||||
const mergedOptions = cachedCleverMerge(originalResolveOptions, options);
|
||||
const resolver = this.get(type, mergedOptions);
|
||||
childCache.set(options, resolver);
|
||||
return resolver;
|
||||
|
|
|
@ -37,6 +37,8 @@ const RequireContextPlugin = require("./dependencies/RequireContextPlugin");
|
|||
const RequireEnsurePlugin = require("./dependencies/RequireEnsurePlugin");
|
||||
const RequireIncludePlugin = require("./dependencies/RequireIncludePlugin");
|
||||
|
||||
const { cachedCleverMerge } = require("./util/cleverMerge");
|
||||
|
||||
/** @typedef {import("../declarations/WebpackOptions").WebpackOptions} WebpackOptions */
|
||||
/** @typedef {import("./Compiler")} Compiler */
|
||||
|
||||
|
@ -512,8 +514,7 @@ class WebpackOptionsApply extends OptionsApply {
|
|||
{
|
||||
fileSystem: compiler.inputFileSystem
|
||||
},
|
||||
options.resolve,
|
||||
resolveOptions
|
||||
cachedCleverMerge(options.resolve, resolveOptions)
|
||||
);
|
||||
});
|
||||
compiler.resolverFactory.hooks.resolveOptions
|
||||
|
@ -524,8 +525,7 @@ class WebpackOptionsApply extends OptionsApply {
|
|||
fileSystem: compiler.inputFileSystem,
|
||||
resolveToContext: true
|
||||
},
|
||||
options.resolve,
|
||||
resolveOptions
|
||||
cachedCleverMerge(options.resolve, resolveOptions)
|
||||
);
|
||||
});
|
||||
compiler.resolverFactory.hooks.resolveOptions
|
||||
|
@ -535,8 +535,7 @@ class WebpackOptionsApply extends OptionsApply {
|
|||
{
|
||||
fileSystem: compiler.inputFileSystem
|
||||
},
|
||||
options.resolveLoader,
|
||||
resolveOptions
|
||||
cachedCleverMerge(options.resolveLoader, resolveOptions)
|
||||
);
|
||||
});
|
||||
compiler.hooks.afterResolvers.call(compiler);
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const mergeCache = new WeakMap();
|
||||
|
||||
/**
|
||||
* Merges two given objects and caches the result to avoid computation if same objects passed as arguments again.
|
||||
* @example
|
||||
* // performs cleverMerge(first, second), stores the result in WeakMap and returns result
|
||||
* cachedCleverMerge({a: 1}, {a: 2})
|
||||
* {a: 2}
|
||||
* // when same arguments passed, gets the result from WeakMap and returns it.
|
||||
* cachedCleverMerge({a: 1}, {a: 2})
|
||||
* {a: 2}
|
||||
* @param {object} first first object
|
||||
* @param {object} second second object
|
||||
* @returns {object} merged object of first and second object
|
||||
*/
|
||||
const cachedCleverMerge = (first, second) => {
|
||||
let innerCache = mergeCache.get(first);
|
||||
if (innerCache === undefined) {
|
||||
innerCache = new WeakMap();
|
||||
mergeCache.set(first, innerCache);
|
||||
}
|
||||
const prevMerge = innerCache.get(second);
|
||||
if (prevMerge !== undefined) return prevMerge;
|
||||
const newMerge = cleverMerge(first, second);
|
||||
innerCache.set(second, newMerge);
|
||||
return newMerge;
|
||||
};
|
||||
|
||||
/**
|
||||
* Merges two objects. Objects are not deeply merged.
|
||||
* TODO webpack 5: merge objects deeply clever.
|
||||
* Arrays might reference the old value with "..."
|
||||
* @param {object} first first object
|
||||
* @param {object} second second object
|
||||
* @returns {object} merged object of first and second object
|
||||
*/
|
||||
const cleverMerge = (first, second) => {
|
||||
const newObject = Object.assign({}, first);
|
||||
for (const key of Object.keys(second)) {
|
||||
if (!(key in newObject)) {
|
||||
newObject[key] = second[key];
|
||||
continue;
|
||||
}
|
||||
const secondValue = second[key];
|
||||
if (!Array.isArray(secondValue)) {
|
||||
newObject[key] = secondValue;
|
||||
continue;
|
||||
}
|
||||
const firstValue = newObject[key];
|
||||
if (Array.isArray(firstValue)) {
|
||||
const newArray = [];
|
||||
for (const item of secondValue) {
|
||||
if (item === "...") {
|
||||
for (const item of firstValue) {
|
||||
newArray.push(item);
|
||||
}
|
||||
} else {
|
||||
newArray.push(item);
|
||||
}
|
||||
}
|
||||
newObject[key] = newArray;
|
||||
} else {
|
||||
newObject[key] = secondValue;
|
||||
}
|
||||
}
|
||||
return newObject;
|
||||
};
|
||||
|
||||
exports.cachedCleverMerge = cachedCleverMerge;
|
||||
exports.cleverMerge = cleverMerge;
|
|
@ -2,6 +2,9 @@ it("should be possible to create resolver with different options", () => {
|
|||
const result = require("./loader!");
|
||||
expect(result).toEqual({
|
||||
one: "index.js",
|
||||
two: "index.xyz"
|
||||
two: "index.xyz",
|
||||
three: "index.js",
|
||||
four: "index.xyz",
|
||||
five: "index.js"
|
||||
});
|
||||
})
|
||||
});
|
||||
|
|
|
@ -4,13 +4,28 @@ module.exports = function() {
|
|||
const resolve2 = this.getResolve({
|
||||
extensions: [".xyz", ".js"]
|
||||
});
|
||||
const resolve3 = this.getResolve({
|
||||
extensions: [".hee", "..."]
|
||||
});
|
||||
const resolve4 = this.getResolve({
|
||||
extensions: [".xyz", "..."]
|
||||
});
|
||||
const resolve5 = this.getResolve({
|
||||
extensions: ["...", ".xyz"]
|
||||
});
|
||||
return Promise.all([
|
||||
resolve1(__dirname, "./index"),
|
||||
resolve2(__dirname, "./index")
|
||||
]).then(([one, two]) => {
|
||||
resolve2(__dirname, "./index"),
|
||||
resolve3(__dirname, "./index"),
|
||||
resolve4(__dirname, "./index"),
|
||||
resolve5(__dirname, "./index")
|
||||
]).then(([one, two, three, four, five]) => {
|
||||
return `module.exports = ${JSON.stringify({
|
||||
one: path.basename(one),
|
||||
two: path.basename(two),
|
||||
three: path.basename(three),
|
||||
four: path.basename(four),
|
||||
five: path.basename(five)
|
||||
})}`;
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1 +1 @@
|
|||
module.exports = require("./wrong");
|
||||
module.exports = require("./wrong") + require("./normal") + require("./wrong2");
|
||||
|
|
|
@ -1 +1 @@
|
|||
module.exports = require("./wrong");
|
||||
module.exports = require("./wrong") + require("./normal") + require("./wrong2");
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
module.exports = require("./wrong") + require("./normal") + require("./wrong2");
|
|
@ -1,6 +1,8 @@
|
|||
it("should allow to set custom resolving rules", function() {
|
||||
var a = require("./a");
|
||||
expect(a).toBe("ok");
|
||||
expect(a).toBe("ok-normal-wrong2");
|
||||
var b = require("./b");
|
||||
expect(b).toBe("wrong");
|
||||
expect(b).toBe("ok-normal-wrong2-yes");
|
||||
var c = require("./c");
|
||||
expect(c).toBe("wrong-normal-ok2");
|
||||
});
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
module.exports = "-normal-";
|
|
@ -0,0 +1 @@
|
|||
module.exports = "ok-ok";
|
|
@ -0,0 +1 @@
|
|||
module.exports = "ok2";
|
|
@ -0,0 +1 @@
|
|||
module.exports = "ok2-yes";
|
|
@ -1,4 +1,9 @@
|
|||
module.exports = {
|
||||
resolve: {
|
||||
alias: {
|
||||
"./wrong2": "./ok2"
|
||||
}
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
|
@ -6,7 +11,23 @@ module.exports = {
|
|||
resolve: {
|
||||
alias: {
|
||||
"./wrong": "./ok"
|
||||
}
|
||||
},
|
||||
extensions: [".js", ".ok.js"]
|
||||
}
|
||||
},
|
||||
{
|
||||
test: require.resolve("./b"),
|
||||
resolve: {
|
||||
alias: {
|
||||
"./wrong": "./ok"
|
||||
},
|
||||
extensions: ["...", ".ok.js"]
|
||||
}
|
||||
},
|
||||
{
|
||||
test: require.resolve("./b"),
|
||||
resolve: {
|
||||
extensions: [".yes.js", "..."]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
module.exports = "wrong2";
|
|
@ -0,0 +1 @@
|
|||
module.exports = "wrong2-yes";
|
正在加载...
在新工单中引用