TeaWeb/webpack/ManifestPlugin.ts

109 lines
3.8 KiB
TypeScript
Raw Normal View History

2020-03-30 23:27:59 +00:00
import * as webpack from "webpack";
import * as fs from "fs-extra";
import * as path from "path";
2020-03-30 23:27:59 +00:00
interface Options {
file?: string;
base: string;
2020-03-30 23:27:59 +00:00
}
class ManifestGenerator {
private manifest_content;
readonly options: Options;
constructor(options: Options) {
this.options = options || { base: __dirname };
2020-03-30 23:27:59 +00:00
}
apply(compiler: webpack.Compiler) {
compiler.hooks.afterCompile.tap(this.constructor.name, compilation => {
const chunks_data = {};
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.length)
continue;
2020-09-01 10:53:42 +00:00
/*
2020-04-09 14:14:54 +00:00
if(chunk.files.length !== 1) {
2020-04-09 21:09:59 +00:00
console.error("Expected only one file per chunk but got " + chunk.files.length);
2020-04-09 14:14:54 +00:00
chunk.files.forEach(e => console.log(" - %s", e));
throw "expected only one file per chunk";
}
2020-09-01 10:53:42 +00:00
*/
2020-04-09 14:14:54 +00:00
for(const file of chunk.files) {
const extension = path.extname(file);
2020-08-09 12:30:17 +00:00
if(extension === ".js") {
fileJs.push({
2020-04-09 14:14:54 +00:00
hash: chunk.hash,
file: file
});
2020-08-09 12:30:17 +00:00
} else if(extension === ".css") {
filesCss.push({
2020-04-09 14:14:54 +00:00
hash: chunk.hash,
file: file
});
2020-09-01 10:53:42 +00:00
} else if(extension === ".wasm") {
/* do nothing */
2020-08-09 12:30:17 +00:00
} else {
2020-04-09 14:14:54 +00:00
throw "Unknown chunk file with extension " + extension;
2020-08-09 12:30:17 +00:00
}
2020-04-09 14:14:54 +00:00
}
2020-08-09 12:30:17 +00:00
for(const module of chunk.getModules()) {
if(!module.type.startsWith("javascript/"))
continue;
2020-08-09 12:30:17 +00:00
if(!module.context)
continue;
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.base, module.context).replace(/\\/g, "/"),
resource: path.basename(module.resource)
});
}
2020-03-30 23:27:59 +00:00
}
2020-08-09 12:30:17 +00:00
chunks_data[chunkGroup.options.name] = {
files: fileJs,
css_files: filesCss,
modules: modules
};
2020-03-30 23:27:59 +00:00
}
this.manifest_content = {
version: 2,
2020-03-30 23:27:59 +00:00
chunks: chunks_data
};
});
compiler.hooks.done.tap(this.constructor.name, () => {
const file = this.options.file || "manifest.json";
fs.mkdirpSync(path.dirname(file));
2020-03-30 23:27:59 +00:00
fs.writeFileSync(this.options.file || "manifest.json", JSON.stringify(this.manifest_content));
});
}
}
export = ManifestGenerator;