2020-02-25 04:34:09 +01:00
|
|
|
// This plugin exposes a version of require() to the browser console to assist
|
|
|
|
// debugging. It also exposes the list of modules it knows about as the keys
|
|
|
|
// of the require.ids object.
|
|
|
|
|
|
|
|
import webpack, { Template } from "webpack";
|
|
|
|
import path from "path";
|
|
|
|
|
|
|
|
export default class DebugRequirePlugin {
|
|
|
|
apply(compiler: webpack.Compiler): void {
|
|
|
|
const resolved = new Map();
|
|
|
|
const nameSymbol = Symbol("DebugRequirePluginName");
|
2020-02-25 08:18:50 +01:00
|
|
|
let debugRequirePath: string | undefined;
|
2020-02-25 04:34:09 +01:00
|
|
|
|
|
|
|
(compiler as any).resolverFactory.hooks.resolver
|
|
|
|
.for("normal")
|
|
|
|
.tap("DebugRequirePlugin", (resolver: any) => {
|
|
|
|
resolver.getHook("beforeRawModule").tap("DebugRequirePlugin", (req: any) => {
|
|
|
|
req[nameSymbol] = req[nameSymbol] || req.request;
|
|
|
|
});
|
|
|
|
|
|
|
|
resolver.getHook("beforeRelative").tap("DebugRequirePlugin", (req: any) => {
|
|
|
|
const inPath = path.relative(compiler.context, req.path);
|
|
|
|
if (!inPath.startsWith("../")) {
|
|
|
|
req[nameSymbol] = req[nameSymbol] || "./" + inPath;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
resolver.getHook("beforeResolved").tap("DebugRequirePlugin", (req: any) => {
|
|
|
|
if (req[nameSymbol]) {
|
|
|
|
const names = resolved.get(req.path);
|
|
|
|
if (names) {
|
|
|
|
names.add(req[nameSymbol]);
|
|
|
|
} else {
|
|
|
|
resolved.set(req.path, new Set([req[nameSymbol]]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-02-25 08:18:50 +01:00
|
|
|
compiler.hooks.beforeCompile.tapPromise(
|
|
|
|
"DebugRequirePlugin",
|
|
|
|
async ({ normalModuleFactory }: any) => {
|
|
|
|
const resolver = normalModuleFactory.getResolver("normal");
|
|
|
|
debugRequirePath = await new Promise((resolve, reject) =>
|
|
|
|
resolver.resolve(
|
|
|
|
{},
|
|
|
|
__dirname,
|
|
|
|
"./debug-require.js",
|
|
|
|
{},
|
2020-07-02 02:16:03 +02:00
|
|
|
(err?: Error, result?: string) => err ? reject(err) : resolve(result),
|
|
|
|
),
|
2020-02-25 08:18:50 +01:00
|
|
|
);
|
2020-07-02 02:16:03 +02:00
|
|
|
},
|
2020-02-25 08:18:50 +01:00
|
|
|
);
|
|
|
|
|
2020-02-25 04:34:09 +01:00
|
|
|
compiler.hooks.compilation.tap("DebugRequirePlugin", (compilation: any) => {
|
|
|
|
compilation.mainTemplate.hooks.beforeStartup.tap(
|
|
|
|
"DebugRequirePlugin",
|
|
|
|
(source: string, chunk: webpack.compilation.Chunk) => {
|
|
|
|
const ids: [string, string | number][] = [];
|
2020-02-25 08:18:50 +01:00
|
|
|
let debugRequireId;
|
2020-02-25 04:34:09 +01:00
|
|
|
chunk.hasModuleInGraph(
|
2020-02-25 08:18:50 +01:00
|
|
|
({ resource, rawRequest, id }: any) => {
|
|
|
|
if (resource === debugRequirePath) {
|
|
|
|
debugRequireId = id;
|
|
|
|
}
|
2020-02-25 04:34:09 +01:00
|
|
|
for (const name of resolved.get(resource) || []) {
|
|
|
|
ids.push([
|
|
|
|
rawRequest.slice(0, rawRequest.lastIndexOf("!") + 1) + name,
|
|
|
|
id,
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
},
|
2020-07-02 02:16:03 +02:00
|
|
|
() => true,
|
2020-02-25 04:34:09 +01:00
|
|
|
);
|
|
|
|
|
2020-02-25 08:18:50 +01:00
|
|
|
if (debugRequireId === undefined) {
|
|
|
|
return source;
|
|
|
|
}
|
2020-02-25 04:34:09 +01:00
|
|
|
|
2020-02-25 08:18:50 +01:00
|
|
|
ids.sort();
|
|
|
|
const { requireFn } = compilation.mainTemplate;
|
2020-02-25 04:34:09 +01:00
|
|
|
return Template.asString([
|
|
|
|
source,
|
2020-02-25 08:18:50 +01:00
|
|
|
`${requireFn}(${JSON.stringify(
|
2020-07-02 02:16:03 +02:00
|
|
|
debugRequireId,
|
2020-02-25 08:18:50 +01:00
|
|
|
)}).initialize(${JSON.stringify(Object.fromEntries(ids), null, "\t")});`,
|
2020-02-25 04:34:09 +01:00
|
|
|
]);
|
2020-07-02 02:16:03 +02:00
|
|
|
},
|
2020-02-25 04:34:09 +01:00
|
|
|
);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|