TeaWeb/webpack/ManifestPlugin.ts

110 lines
3.7 KiB
TypeScript
Raw Normal View History

2020-03-30 23:27:59 +00:00
import * as webpack from "webpack";
import * as path from "path";
2020-03-30 23:27:59 +00:00
interface Options {
outputFileName?: string;
context: string;
2020-03-30 23:27:59 +00:00
}
class ManifestGenerator {
private readonly options: Options;
2020-03-30 23:27:59 +00:00
constructor(options: Options) {
this.options = options || { context: __dirname };
2020-03-30 23:27:59 +00:00
}
apply(compiler: webpack.Compiler) {
compiler.hooks.emit.tap("ManifestGenerator", compilation => {
const chunkData = {};
2020-08-09 12:30:17 +00:00
for(const chunkGroup of compilation.chunkGroups) {
const fileJs = [];
const filesCss = [];
const modules = [];
2020-08-09 12:30:17 +00:00
for(const chunk of chunkGroup.chunks) {
if(!chunk.files.size) {
2020-08-09 12:30:17 +00:00
continue;
2020-04-09 14:14:54 +00:00
}
2020-04-09 14:14:54 +00:00
for(const file of chunk.files) {
const extension = path.extname(file);
switch (extension) {
case ".js":
fileJs.push({
hash: chunk.hash,
file: file
});
break;
case ".css":
filesCss.push({
hash: chunk.hash,
file: file
});
break;
case ".wasm":
break;
default:
throw "Unknown chunk file with extension " + extension;
2020-08-09 12:30:17 +00:00
}
2020-04-09 14:14:54 +00:00
}
for(const module of chunk.getModules() as any[]) {
if(!module.type.startsWith("javascript/")) {
continue;
}
if(!module.context) {
2020-08-09 12:30:17 +00:00
continue;
}
2020-08-09 12:30:17 +00:00
if(module.context.startsWith("svg-sprites/")) {
/* custom svg sprite handler */
modules.push({
id: module.id,
context: "svg-sprites",
resource: module.context.substring("svg-sprites/".length)
});
continue;
}
if(!module.resource) {
continue;
}
if(module.context !== path.dirname(module.resource)) {
throw "invalid context/resource relation";
}
modules.push({
id: module.id,
context: path.relative(this.options.context, module.context).replace(/\\/g, "/"),
resource: path.basename(module.resource)
});
}
2020-03-30 23:27:59 +00:00
}
chunkData[chunkGroup.options.name] = {
2020-08-09 12:30:17 +00:00
files: fileJs,
css_files: filesCss,
modules: modules
};
2020-03-30 23:27:59 +00:00
}
const payload = JSON.stringify({
version: 2,
chunks: chunkData
});
const fileName = this.options.outputFileName || "manifest.json";
compilation.assets[fileName] = {
size() { return payload.length; },
source() { return payload; }
} as any;
2020-03-30 23:27:59 +00:00
});
}
}
export = ManifestGenerator;