Skip to content

Commit 530e1fb

Browse files
committed
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
1 parent 3415a98 commit 530e1fb

File tree

10 files changed

+140
-26
lines changed

10 files changed

+140
-26
lines changed

lib/NormalModule.js

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,18 @@ const contextify = (context, request) => {
4343
.split("!")
4444
.map(r => {
4545
const splitPath = r.split("?");
46-
splitPath[0] = path.relative(context, splitPath[0]);
47-
if (path.sep === "\\") splitPath[0] = splitPath[0].replace(/\\/g, "/");
48-
if (splitPath[0].indexOf("../") !== 0) splitPath[0] = "./" + splitPath[0];
46+
if (/^[a-zA-Z]:\\/.test(splitPath[0])) {
47+
splitPath[0] = path.win32.relative(context, splitPath[0]);
48+
if (!/^[a-zA-Z]:\\/.test(splitPath[0])) {
49+
splitPath[0] = splitPath[0].replace(/\\/g, "/");
50+
}
51+
}
52+
if (/^\//.test(splitPath[0])) {
53+
splitPath[0] = path.posix.relative(context, splitPath[0]);
54+
}
55+
if (!/^(\.\.\/|\/|[a-zA-Z]:\\)/.test(splitPath[0])) {
56+
splitPath[0] = "./" + splitPath[0];
57+
}
4958
return splitPath.join("?");
5059
})
5160
.join("!");
@@ -76,6 +85,7 @@ class NormalModule extends Module {
7685
rawRequest,
7786
loaders,
7887
resource,
88+
matchResource,
7989
parser,
8090
generator,
8191
resolveOptions
@@ -90,6 +100,7 @@ class NormalModule extends Module {
90100
this.parser = parser;
91101
this.generator = generator;
92102
this.resource = resource;
103+
this.matchResource = matchResource;
93104
this.loaders = loaders;
94105
if (resolveOptions !== undefined) this.resolveOptions = resolveOptions;
95106

@@ -123,16 +134,21 @@ class NormalModule extends Module {
123134
}
124135

125136
nameForCondition() {
126-
const idx = this.resource.indexOf("?");
127-
if (idx >= 0) return this.resource.substr(0, idx);
128-
return this.resource;
137+
const resource = this.matchResource || this.resource;
138+
const idx = resource.indexOf("?");
139+
if (idx >= 0) return resource.substr(0, idx);
140+
return resource;
129141
}
130142

131143
updateCacheModule(module) {
144+
this.type = module.type;
145+
this.request = module.request;
132146
this.userRequest = module.userRequest;
147+
this.rawRequest = module.rawRequest;
133148
this.parser = module.parser;
134149
this.generator = module.generator;
135150
this.resource = module.resource;
151+
this.matchResource = module.matchResource;
136152
this.loaders = module.loaders;
137153
this.resolveOptions = module.resolveOptions;
138154
}

lib/NormalModuleFactory.js

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
"use strict";
66

7+
const path = require("path");
78
const asyncLib = require("neo-async");
89
const {
910
Tapable,
@@ -20,6 +21,8 @@ const cachedMerge = require("./util/cachedMerge");
2021

2122
const EMPTY_RESOLVE_OPTIONS = {};
2223

24+
const MATCH_RESOURCE_REGEX = /^([^!]+)!=!/;
25+
2326
const loaderToIdent = data => {
2427
if (!data.options) {
2528
return data.loader;
@@ -158,19 +161,33 @@ class NormalModuleFactory extends Tapable {
158161
const context = data.context;
159162
const request = data.request;
160163

161-
const noPreAutoLoaders = request.startsWith("-!");
162-
const noAutoLoaders = noPreAutoLoaders || request.startsWith("!");
163-
const noPrePostAutoLoaders = request.startsWith("!!");
164-
let elements = request
164+
const loaderResolver = this.getResolver("loader");
165+
const normalResolver = this.getResolver("normal", data.resolveOptions);
166+
167+
let matchResource = undefined;
168+
let requestWithoutMatchResource = request;
169+
const matchResourceMatch = MATCH_RESOURCE_REGEX.exec(request);
170+
if (matchResourceMatch) {
171+
matchResource = matchResourceMatch[1];
172+
if (/^\.\.?\//.test(matchResource)) {
173+
matchResource = path.join(context, matchResource);
174+
}
175+
requestWithoutMatchResource = request.substr(
176+
matchResourceMatch[0].length
177+
);
178+
}
179+
180+
const noPreAutoLoaders = requestWithoutMatchResource.startsWith("-!");
181+
const noAutoLoaders =
182+
noPreAutoLoaders || requestWithoutMatchResource.startsWith("!");
183+
const noPrePostAutoLoaders = requestWithoutMatchResource.startsWith("!!");
184+
let elements = requestWithoutMatchResource
165185
.replace(/^-?!+/, "")
166186
.replace(/!!+/g, "!")
167187
.split("!");
168188
let resource = elements.pop();
169189
elements = elements.map(identToLoaderRequest);
170190

171-
const loaderResolver = this.getResolver("loader");
172-
const normalResolver = this.getResolver("normal", data.resolveOptions);
173-
174191
asyncLib.parallel(
175192
[
176193
callback =>
@@ -234,12 +251,15 @@ class NormalModuleFactory extends Tapable {
234251
);
235252
}
236253

237-
const userRequest = loaders
238-
.map(loaderToIdent)
239-
.concat([resource])
240-
.join("!");
254+
const userRequest =
255+
(matchResource !== undefined ? `${matchResource}!=!` : "") +
256+
loaders
257+
.map(loaderToIdent)
258+
.concat([resource])
259+
.join("!");
241260

242-
let resourcePath = resource;
261+
let resourcePath =
262+
matchResource !== undefined ? matchResource : resource;
243263
let resourceQuery = "";
244264
const queryIndex = resourcePath.indexOf("?");
245265
if (queryIndex >= 0) {
@@ -249,6 +269,10 @@ class NormalModuleFactory extends Tapable {
249269

250270
const result = this.ruleSet.exec({
251271
resource: resourcePath,
272+
realResource:
273+
matchResource !== undefined
274+
? resource.replace(/\?.*/, "")
275+
: resourcePath,
252276
resourceQuery,
253277
issuer: contextInfo.issuer,
254278
compiler: contextInfo.compiler
@@ -326,6 +350,7 @@ class NormalModuleFactory extends Tapable {
326350
rawRequest: request,
327351
loaders,
328352
resource,
353+
matchResource,
329354
resourceResolveData,
330355
settings,
331356
type,

lib/RequestShortener.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const PATH_CHARS_REGEXP = /[-[\]{}()*+?.,\\^$|#\s]/g;
1010
const SEPARATOR_REGEXP = /[/\\]$/;
1111
const FRONT_OR_BACK_BANG_REGEXP = /^!|!$/g;
1212
const INDEX_JS_REGEXP = /\/index.js(!|\?|\(query\))/g;
13+
const MATCH_RESOURCE_REGEXP = /!=!/;
1314

1415
const normalizeBackSlashDirection = request => {
1516
return request.replace(NORMALIZE_SLASH_DIRECTION_REGEXP, "/");
@@ -73,6 +74,7 @@ class RequestShortener {
7374
}
7475
result = result.replace(INDEX_JS_REGEXP, "$1");
7576
result = result.replace(FRONT_OR_BACK_BANG_REGEXP, "");
77+
result = result.replace(MATCH_RESOURCE_REGEXP, " = ");
7678
this.cache.set(request, result);
7779
return result;
7880
}

lib/RuleSet.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,14 @@ module.exports = class RuleSet {
203203
}
204204
}
205205

206+
if (rule.realResource) {
207+
try {
208+
newRule.realResource = RuleSet.normalizeCondition(rule.realResource);
209+
} catch (error) {
210+
throw new Error(RuleSet.buildErrorMessage(rule.realResource, error));
211+
}
212+
}
213+
206214
if (rule.resourceQuery) {
207215
try {
208216
newRule.resourceQuery = RuleSet.normalizeCondition(rule.resourceQuery);
@@ -477,10 +485,13 @@ module.exports = class RuleSet {
477485
_run(data, rule, result) {
478486
// test conditions
479487
if (rule.resource && !data.resource) return false;
488+
if (rule.realResource && !data.realResource) return false;
480489
if (rule.resourceQuery && !data.resourceQuery) return false;
481490
if (rule.compiler && !data.compiler) return false;
482491
if (rule.issuer && !data.issuer) return false;
483492
if (rule.resource && !rule.resource(data.resource)) return false;
493+
if (rule.realResource && !rule.realResource(data.realResource))
494+
return false;
484495
if (data.issuer && rule.issuer && !rule.issuer(data.issuer)) return false;
485496
if (
486497
data.resourceQuery &&
@@ -497,6 +508,7 @@ module.exports = class RuleSet {
497508
const keys = Object.keys(rule).filter(key => {
498509
return ![
499510
"resource",
511+
"realResource",
500512
"resourceQuery",
501513
"compiler",
502514
"issuer",

test/NormalModule.unittest.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ describe("NormalModule", () => {
1616
let resource;
1717
let parser;
1818
beforeEach(() => {
19-
request = "some/request";
20-
userRequest = "some/userRequest";
19+
request = "/some/request";
20+
userRequest = "/some/userRequest";
2121
rawRequest = "some/rawRequest";
2222
loaders = [];
23-
resource = "some/resource";
23+
resource = "/some/resource";
2424
parser = {
2525
parse() {}
2626
};
@@ -66,14 +66,14 @@ describe("NormalModule", () => {
6666
it("contextifies the userRequest of the module", () => {
6767
expect(
6868
normalModule.libIdent({
69-
context: "some/context"
69+
context: "/some/context"
7070
})
7171
).toBe("../userRequest");
7272
});
7373
describe("given a userRequest containing loaders", () => {
7474
beforeEach(() => {
7575
userRequest =
76-
"some/userRequest!some/other/userRequest!some/thing/is/off/here";
76+
"/some/userRequest!/some/other/userRequest!/some/thing/is/off/here";
7777
normalModule = new NormalModule({
7878
type: "javascript/auto",
7979
request,
@@ -87,15 +87,15 @@ describe("NormalModule", () => {
8787
it("contextifies every path in the userRequest", () => {
8888
expect(
8989
normalModule.libIdent({
90-
context: "some/context"
90+
context: "/some/context"
9191
})
9292
).toBe("../userRequest!../other/userRequest!../thing/is/off/here");
9393
});
9494
});
9595
describe("given a userRequest containing query parameters", () => {
9696
it("ignores paths in query parameters", () => {
9797
userRequest =
98-
"some/context/loader?query=foo\\bar&otherPath=testpath/other";
98+
"F:\\some\\context\\loader?query=foo\\bar&otherPath=testpath/other";
9999
normalModule = new NormalModule({
100100
type: "javascript/auto",
101101
request,
@@ -107,7 +107,7 @@ describe("NormalModule", () => {
107107
});
108108
expect(
109109
normalModule.libIdent({
110-
context: "some/context"
110+
context: "F:\\some\\context"
111111
})
112112
).toBe("./loader?query=foo\\bar&otherPath=testpath/other");
113113
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
it("should be able to create two modules from loader", function() {
2+
return import("./wrapper-loader!./src/wasm.dat").then(function(wasm) {
3+
expect(wasm.getString()).toEqual("Hello World");
4+
});
5+
});
6+
7+
it("should be able to create two modules from loader with remaining request", function() {
8+
return import("./wrapper-loader2!./src/wasm.dat?2").then(function(wasm) {
9+
expect(wasm.getString()).toEqual("Hello World");
10+
});
11+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
(module
2+
(memory (export "memory") 1)
3+
(data (i32.const 16) "Hello World\00")
4+
(func (export "getString") (result i32)
5+
(i32.const 16)
6+
)
7+
)
8+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
var supportsWebAssembly = require("../../../helpers/supportsWebAssembly");
2+
3+
module.exports = function(config) {
4+
return supportsWebAssembly();
5+
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const stringifyRequest = require("loader-utils").stringifyRequest;
2+
3+
module.exports.pitch = function(remainingRequest) {
4+
return `
5+
import { getString as _getString, memory } from ${stringifyRequest(this,
6+
`${this.resourcePath}.wat!=!${remainingRequest}`
7+
)};
8+
9+
export function getString() {
10+
const strBuf = new Uint8Array(memory.buffer, _getString());
11+
const idx = strBuf.indexOf(0);
12+
const strBuf2 = strBuf.slice(0, idx);
13+
const str = Buffer.from(strBuf2).toString("utf-8");
14+
return str;
15+
};
16+
`;
17+
};
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const stringifyRequest = require("loader-utils").stringifyRequest;
2+
3+
module.exports.pitch = function(remainingRequest) {
4+
return `
5+
import { getString as _getString, memory } from ${stringifyRequest(
6+
this,
7+
`${this.resourcePath}.wasm!=!wast-loader!${remainingRequest}`
8+
)};
9+
10+
export function getString() {
11+
const strBuf = new Uint8Array(memory.buffer, _getString());
12+
const idx = strBuf.indexOf(0);
13+
const strBuf2 = strBuf.slice(0, idx);
14+
const str = Buffer.from(strBuf2).toString("utf-8");
15+
return str;
16+
};
17+
`;
18+
};

0 commit comments

Comments
 (0)