Add matchResource feature (for loaders)
Match rules with custom resource name Also use this name as rule.issuer or splitChunks test Show nicely in stats
This commit is contained in:
parent
3415a98330
commit
530e1fb172
|
@ -43,9 +43,18 @@ const contextify = (context, request) => {
|
||||||
.split("!")
|
.split("!")
|
||||||
.map(r => {
|
.map(r => {
|
||||||
const splitPath = r.split("?");
|
const splitPath = r.split("?");
|
||||||
splitPath[0] = path.relative(context, splitPath[0]);
|
if (/^[a-zA-Z]:\\/.test(splitPath[0])) {
|
||||||
if (path.sep === "\\") splitPath[0] = splitPath[0].replace(/\\/g, "/");
|
splitPath[0] = path.win32.relative(context, splitPath[0]);
|
||||||
if (splitPath[0].indexOf("../") !== 0) splitPath[0] = "./" + splitPath[0];
|
if (!/^[a-zA-Z]:\\/.test(splitPath[0])) {
|
||||||
|
splitPath[0] = splitPath[0].replace(/\\/g, "/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (/^\//.test(splitPath[0])) {
|
||||||
|
splitPath[0] = path.posix.relative(context, splitPath[0]);
|
||||||
|
}
|
||||||
|
if (!/^(\.\.\/|\/|[a-zA-Z]:\\)/.test(splitPath[0])) {
|
||||||
|
splitPath[0] = "./" + splitPath[0];
|
||||||
|
}
|
||||||
return splitPath.join("?");
|
return splitPath.join("?");
|
||||||
})
|
})
|
||||||
.join("!");
|
.join("!");
|
||||||
|
@ -76,6 +85,7 @@ class NormalModule extends Module {
|
||||||
rawRequest,
|
rawRequest,
|
||||||
loaders,
|
loaders,
|
||||||
resource,
|
resource,
|
||||||
|
matchResource,
|
||||||
parser,
|
parser,
|
||||||
generator,
|
generator,
|
||||||
resolveOptions
|
resolveOptions
|
||||||
|
@ -90,6 +100,7 @@ class NormalModule extends Module {
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
this.generator = generator;
|
this.generator = generator;
|
||||||
this.resource = resource;
|
this.resource = resource;
|
||||||
|
this.matchResource = matchResource;
|
||||||
this.loaders = loaders;
|
this.loaders = loaders;
|
||||||
if (resolveOptions !== undefined) this.resolveOptions = resolveOptions;
|
if (resolveOptions !== undefined) this.resolveOptions = resolveOptions;
|
||||||
|
|
||||||
|
@ -123,16 +134,21 @@ class NormalModule extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
nameForCondition() {
|
nameForCondition() {
|
||||||
const idx = this.resource.indexOf("?");
|
const resource = this.matchResource || this.resource;
|
||||||
if (idx >= 0) return this.resource.substr(0, idx);
|
const idx = resource.indexOf("?");
|
||||||
return this.resource;
|
if (idx >= 0) return resource.substr(0, idx);
|
||||||
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateCacheModule(module) {
|
updateCacheModule(module) {
|
||||||
|
this.type = module.type;
|
||||||
|
this.request = module.request;
|
||||||
this.userRequest = module.userRequest;
|
this.userRequest = module.userRequest;
|
||||||
|
this.rawRequest = module.rawRequest;
|
||||||
this.parser = module.parser;
|
this.parser = module.parser;
|
||||||
this.generator = module.generator;
|
this.generator = module.generator;
|
||||||
this.resource = module.resource;
|
this.resource = module.resource;
|
||||||
|
this.matchResource = module.matchResource;
|
||||||
this.loaders = module.loaders;
|
this.loaders = module.loaders;
|
||||||
this.resolveOptions = module.resolveOptions;
|
this.resolveOptions = module.resolveOptions;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
*/
|
*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
const path = require("path");
|
||||||
const asyncLib = require("neo-async");
|
const asyncLib = require("neo-async");
|
||||||
const {
|
const {
|
||||||
Tapable,
|
Tapable,
|
||||||
|
@ -20,6 +21,8 @@ const cachedMerge = require("./util/cachedMerge");
|
||||||
|
|
||||||
const EMPTY_RESOLVE_OPTIONS = {};
|
const EMPTY_RESOLVE_OPTIONS = {};
|
||||||
|
|
||||||
|
const MATCH_RESOURCE_REGEX = /^([^!]+)!=!/;
|
||||||
|
|
||||||
const loaderToIdent = data => {
|
const loaderToIdent = data => {
|
||||||
if (!data.options) {
|
if (!data.options) {
|
||||||
return data.loader;
|
return data.loader;
|
||||||
|
@ -158,19 +161,33 @@ class NormalModuleFactory extends Tapable {
|
||||||
const context = data.context;
|
const context = data.context;
|
||||||
const request = data.request;
|
const request = data.request;
|
||||||
|
|
||||||
const noPreAutoLoaders = request.startsWith("-!");
|
const loaderResolver = this.getResolver("loader");
|
||||||
const noAutoLoaders = noPreAutoLoaders || request.startsWith("!");
|
const normalResolver = this.getResolver("normal", data.resolveOptions);
|
||||||
const noPrePostAutoLoaders = request.startsWith("!!");
|
|
||||||
let elements = request
|
let matchResource = undefined;
|
||||||
|
let requestWithoutMatchResource = request;
|
||||||
|
const matchResourceMatch = MATCH_RESOURCE_REGEX.exec(request);
|
||||||
|
if (matchResourceMatch) {
|
||||||
|
matchResource = matchResourceMatch[1];
|
||||||
|
if (/^\.\.?\//.test(matchResource)) {
|
||||||
|
matchResource = path.join(context, matchResource);
|
||||||
|
}
|
||||||
|
requestWithoutMatchResource = request.substr(
|
||||||
|
matchResourceMatch[0].length
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const noPreAutoLoaders = requestWithoutMatchResource.startsWith("-!");
|
||||||
|
const noAutoLoaders =
|
||||||
|
noPreAutoLoaders || requestWithoutMatchResource.startsWith("!");
|
||||||
|
const noPrePostAutoLoaders = requestWithoutMatchResource.startsWith("!!");
|
||||||
|
let elements = requestWithoutMatchResource
|
||||||
.replace(/^-?!+/, "")
|
.replace(/^-?!+/, "")
|
||||||
.replace(/!!+/g, "!")
|
.replace(/!!+/g, "!")
|
||||||
.split("!");
|
.split("!");
|
||||||
let resource = elements.pop();
|
let resource = elements.pop();
|
||||||
elements = elements.map(identToLoaderRequest);
|
elements = elements.map(identToLoaderRequest);
|
||||||
|
|
||||||
const loaderResolver = this.getResolver("loader");
|
|
||||||
const normalResolver = this.getResolver("normal", data.resolveOptions);
|
|
||||||
|
|
||||||
asyncLib.parallel(
|
asyncLib.parallel(
|
||||||
[
|
[
|
||||||
callback =>
|
callback =>
|
||||||
|
@ -234,12 +251,15 @@ class NormalModuleFactory extends Tapable {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const userRequest = loaders
|
const userRequest =
|
||||||
.map(loaderToIdent)
|
(matchResource !== undefined ? `${matchResource}!=!` : "") +
|
||||||
.concat([resource])
|
loaders
|
||||||
.join("!");
|
.map(loaderToIdent)
|
||||||
|
.concat([resource])
|
||||||
|
.join("!");
|
||||||
|
|
||||||
let resourcePath = resource;
|
let resourcePath =
|
||||||
|
matchResource !== undefined ? matchResource : resource;
|
||||||
let resourceQuery = "";
|
let resourceQuery = "";
|
||||||
const queryIndex = resourcePath.indexOf("?");
|
const queryIndex = resourcePath.indexOf("?");
|
||||||
if (queryIndex >= 0) {
|
if (queryIndex >= 0) {
|
||||||
|
@ -249,6 +269,10 @@ class NormalModuleFactory extends Tapable {
|
||||||
|
|
||||||
const result = this.ruleSet.exec({
|
const result = this.ruleSet.exec({
|
||||||
resource: resourcePath,
|
resource: resourcePath,
|
||||||
|
realResource:
|
||||||
|
matchResource !== undefined
|
||||||
|
? resource.replace(/\?.*/, "")
|
||||||
|
: resourcePath,
|
||||||
resourceQuery,
|
resourceQuery,
|
||||||
issuer: contextInfo.issuer,
|
issuer: contextInfo.issuer,
|
||||||
compiler: contextInfo.compiler
|
compiler: contextInfo.compiler
|
||||||
|
@ -326,6 +350,7 @@ class NormalModuleFactory extends Tapable {
|
||||||
rawRequest: request,
|
rawRequest: request,
|
||||||
loaders,
|
loaders,
|
||||||
resource,
|
resource,
|
||||||
|
matchResource,
|
||||||
resourceResolveData,
|
resourceResolveData,
|
||||||
settings,
|
settings,
|
||||||
type,
|
type,
|
||||||
|
|
|
@ -10,6 +10,7 @@ const PATH_CHARS_REGEXP = /[-[\]{}()*+?.,\\^$|#\s]/g;
|
||||||
const SEPARATOR_REGEXP = /[/\\]$/;
|
const SEPARATOR_REGEXP = /[/\\]$/;
|
||||||
const FRONT_OR_BACK_BANG_REGEXP = /^!|!$/g;
|
const FRONT_OR_BACK_BANG_REGEXP = /^!|!$/g;
|
||||||
const INDEX_JS_REGEXP = /\/index.js(!|\?|\(query\))/g;
|
const INDEX_JS_REGEXP = /\/index.js(!|\?|\(query\))/g;
|
||||||
|
const MATCH_RESOURCE_REGEXP = /!=!/;
|
||||||
|
|
||||||
const normalizeBackSlashDirection = request => {
|
const normalizeBackSlashDirection = request => {
|
||||||
return request.replace(NORMALIZE_SLASH_DIRECTION_REGEXP, "/");
|
return request.replace(NORMALIZE_SLASH_DIRECTION_REGEXP, "/");
|
||||||
|
@ -73,6 +74,7 @@ class RequestShortener {
|
||||||
}
|
}
|
||||||
result = result.replace(INDEX_JS_REGEXP, "$1");
|
result = result.replace(INDEX_JS_REGEXP, "$1");
|
||||||
result = result.replace(FRONT_OR_BACK_BANG_REGEXP, "");
|
result = result.replace(FRONT_OR_BACK_BANG_REGEXP, "");
|
||||||
|
result = result.replace(MATCH_RESOURCE_REGEXP, " = ");
|
||||||
this.cache.set(request, result);
|
this.cache.set(request, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,6 +203,14 @@ module.exports = class RuleSet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rule.realResource) {
|
||||||
|
try {
|
||||||
|
newRule.realResource = RuleSet.normalizeCondition(rule.realResource);
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(RuleSet.buildErrorMessage(rule.realResource, error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (rule.resourceQuery) {
|
if (rule.resourceQuery) {
|
||||||
try {
|
try {
|
||||||
newRule.resourceQuery = RuleSet.normalizeCondition(rule.resourceQuery);
|
newRule.resourceQuery = RuleSet.normalizeCondition(rule.resourceQuery);
|
||||||
|
@ -477,10 +485,13 @@ module.exports = class RuleSet {
|
||||||
_run(data, rule, result) {
|
_run(data, rule, result) {
|
||||||
// test conditions
|
// test conditions
|
||||||
if (rule.resource && !data.resource) return false;
|
if (rule.resource && !data.resource) return false;
|
||||||
|
if (rule.realResource && !data.realResource) return false;
|
||||||
if (rule.resourceQuery && !data.resourceQuery) return false;
|
if (rule.resourceQuery && !data.resourceQuery) return false;
|
||||||
if (rule.compiler && !data.compiler) return false;
|
if (rule.compiler && !data.compiler) return false;
|
||||||
if (rule.issuer && !data.issuer) return false;
|
if (rule.issuer && !data.issuer) return false;
|
||||||
if (rule.resource && !rule.resource(data.resource)) return false;
|
if (rule.resource && !rule.resource(data.resource)) return false;
|
||||||
|
if (rule.realResource && !rule.realResource(data.realResource))
|
||||||
|
return false;
|
||||||
if (data.issuer && rule.issuer && !rule.issuer(data.issuer)) return false;
|
if (data.issuer && rule.issuer && !rule.issuer(data.issuer)) return false;
|
||||||
if (
|
if (
|
||||||
data.resourceQuery &&
|
data.resourceQuery &&
|
||||||
|
@ -497,6 +508,7 @@ module.exports = class RuleSet {
|
||||||
const keys = Object.keys(rule).filter(key => {
|
const keys = Object.keys(rule).filter(key => {
|
||||||
return ![
|
return ![
|
||||||
"resource",
|
"resource",
|
||||||
|
"realResource",
|
||||||
"resourceQuery",
|
"resourceQuery",
|
||||||
"compiler",
|
"compiler",
|
||||||
"issuer",
|
"issuer",
|
||||||
|
|
|
@ -16,11 +16,11 @@ describe("NormalModule", () => {
|
||||||
let resource;
|
let resource;
|
||||||
let parser;
|
let parser;
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
request = "some/request";
|
request = "/some/request";
|
||||||
userRequest = "some/userRequest";
|
userRequest = "/some/userRequest";
|
||||||
rawRequest = "some/rawRequest";
|
rawRequest = "some/rawRequest";
|
||||||
loaders = [];
|
loaders = [];
|
||||||
resource = "some/resource";
|
resource = "/some/resource";
|
||||||
parser = {
|
parser = {
|
||||||
parse() {}
|
parse() {}
|
||||||
};
|
};
|
||||||
|
@ -66,14 +66,14 @@ describe("NormalModule", () => {
|
||||||
it("contextifies the userRequest of the module", () => {
|
it("contextifies the userRequest of the module", () => {
|
||||||
expect(
|
expect(
|
||||||
normalModule.libIdent({
|
normalModule.libIdent({
|
||||||
context: "some/context"
|
context: "/some/context"
|
||||||
})
|
})
|
||||||
).toBe("../userRequest");
|
).toBe("../userRequest");
|
||||||
});
|
});
|
||||||
describe("given a userRequest containing loaders", () => {
|
describe("given a userRequest containing loaders", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
userRequest =
|
userRequest =
|
||||||
"some/userRequest!some/other/userRequest!some/thing/is/off/here";
|
"/some/userRequest!/some/other/userRequest!/some/thing/is/off/here";
|
||||||
normalModule = new NormalModule({
|
normalModule = new NormalModule({
|
||||||
type: "javascript/auto",
|
type: "javascript/auto",
|
||||||
request,
|
request,
|
||||||
|
@ -87,7 +87,7 @@ describe("NormalModule", () => {
|
||||||
it("contextifies every path in the userRequest", () => {
|
it("contextifies every path in the userRequest", () => {
|
||||||
expect(
|
expect(
|
||||||
normalModule.libIdent({
|
normalModule.libIdent({
|
||||||
context: "some/context"
|
context: "/some/context"
|
||||||
})
|
})
|
||||||
).toBe("../userRequest!../other/userRequest!../thing/is/off/here");
|
).toBe("../userRequest!../other/userRequest!../thing/is/off/here");
|
||||||
});
|
});
|
||||||
|
@ -95,7 +95,7 @@ describe("NormalModule", () => {
|
||||||
describe("given a userRequest containing query parameters", () => {
|
describe("given a userRequest containing query parameters", () => {
|
||||||
it("ignores paths in query parameters", () => {
|
it("ignores paths in query parameters", () => {
|
||||||
userRequest =
|
userRequest =
|
||||||
"some/context/loader?query=foo\\bar&otherPath=testpath/other";
|
"F:\\some\\context\\loader?query=foo\\bar&otherPath=testpath/other";
|
||||||
normalModule = new NormalModule({
|
normalModule = new NormalModule({
|
||||||
type: "javascript/auto",
|
type: "javascript/auto",
|
||||||
request,
|
request,
|
||||||
|
@ -107,7 +107,7 @@ describe("NormalModule", () => {
|
||||||
});
|
});
|
||||||
expect(
|
expect(
|
||||||
normalModule.libIdent({
|
normalModule.libIdent({
|
||||||
context: "some/context"
|
context: "F:\\some\\context"
|
||||||
})
|
})
|
||||||
).toBe("./loader?query=foo\\bar&otherPath=testpath/other");
|
).toBe("./loader?query=foo\\bar&otherPath=testpath/other");
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
it("should be able to create two modules from loader", function() {
|
||||||
|
return import("./wrapper-loader!./src/wasm.dat").then(function(wasm) {
|
||||||
|
expect(wasm.getString()).toEqual("Hello World");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be able to create two modules from loader with remaining request", function() {
|
||||||
|
return import("./wrapper-loader2!./src/wasm.dat?2").then(function(wasm) {
|
||||||
|
expect(wasm.getString()).toEqual("Hello World");
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,8 @@
|
||||||
|
(module
|
||||||
|
(memory (export "memory") 1)
|
||||||
|
(data (i32.const 16) "Hello World\00")
|
||||||
|
(func (export "getString") (result i32)
|
||||||
|
(i32.const 16)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
var supportsWebAssembly = require("../../../helpers/supportsWebAssembly");
|
||||||
|
|
||||||
|
module.exports = function(config) {
|
||||||
|
return supportsWebAssembly();
|
||||||
|
};
|
|
@ -0,0 +1,17 @@
|
||||||
|
const stringifyRequest = require("loader-utils").stringifyRequest;
|
||||||
|
|
||||||
|
module.exports.pitch = function(remainingRequest) {
|
||||||
|
return `
|
||||||
|
import { getString as _getString, memory } from ${stringifyRequest(this,
|
||||||
|
`${this.resourcePath}.wat!=!${remainingRequest}`
|
||||||
|
)};
|
||||||
|
|
||||||
|
export function getString() {
|
||||||
|
const strBuf = new Uint8Array(memory.buffer, _getString());
|
||||||
|
const idx = strBuf.indexOf(0);
|
||||||
|
const strBuf2 = strBuf.slice(0, idx);
|
||||||
|
const str = Buffer.from(strBuf2).toString("utf-8");
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
`;
|
||||||
|
};
|
|
@ -0,0 +1,18 @@
|
||||||
|
const stringifyRequest = require("loader-utils").stringifyRequest;
|
||||||
|
|
||||||
|
module.exports.pitch = function(remainingRequest) {
|
||||||
|
return `
|
||||||
|
import { getString as _getString, memory } from ${stringifyRequest(
|
||||||
|
this,
|
||||||
|
`${this.resourcePath}.wasm!=!wast-loader!${remainingRequest}`
|
||||||
|
)};
|
||||||
|
|
||||||
|
export function getString() {
|
||||||
|
const strBuf = new Uint8Array(memory.buffer, _getString());
|
||||||
|
const idx = strBuf.indexOf(0);
|
||||||
|
const strBuf2 = strBuf.slice(0, idx);
|
||||||
|
const str = Buffer.from(strBuf2).toString("utf-8");
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
`;
|
||||||
|
};
|
Loading…
Reference in New Issue