2020-03-30 23:27:59 +00:00
|
|
|
import * as webpack from "webpack";
|
2020-04-01 19:47:33 +00:00
|
|
|
import * as path from "path";
|
2021-03-17 17:05:39 +00:00
|
|
|
import {Compilation, NormalModule} from "webpack";
|
2020-03-30 23:27:59 +00:00
|
|
|
|
|
|
|
interface Options {
|
2021-03-17 12:28:27 +00:00
|
|
|
outputFileName?: string;
|
|
|
|
context: string;
|
2020-03-30 23:27:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
class ManifestGenerator {
|
2021-03-17 12:28:27 +00:00
|
|
|
private readonly options: Options;
|
2020-03-30 23:27:59 +00:00
|
|
|
|
|
|
|
constructor(options: Options) {
|
2021-03-17 12:28:27 +00:00
|
|
|
this.options = options || { context: __dirname };
|
2020-03-30 23:27:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
apply(compiler: webpack.Compiler) {
|
2021-03-17 17:05:39 +00:00
|
|
|
compiler.hooks.thisCompilation.tap({
|
|
|
|
name: "ManifestGenerator",
|
|
|
|
stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL
|
|
|
|
}, compilation => {
|
|
|
|
compilation.hooks.processAssets.tap("ManifestGenerator", () => this.emitAssets(compilation));
|
|
|
|
});
|
|
|
|
}
|
2020-04-01 19:47:33 +00:00
|
|
|
|
2021-03-17 17:05:39 +00:00
|
|
|
emitAssets(compilation: webpack.Compilation) {
|
|
|
|
const chunkData = {};
|
|
|
|
|
|
|
|
for(const chunkGroup of compilation.chunkGroups) {
|
|
|
|
const fileJs = [];
|
|
|
|
const filesCss = [];
|
|
|
|
const modules = [];
|
|
|
|
|
|
|
|
for(const chunk of chunkGroup.chunks) {
|
|
|
|
if(!chunk.files.size) {
|
|
|
|
continue;
|
|
|
|
}
|
2020-04-01 19:47:33 +00:00
|
|
|
|
2021-03-17 17:05:39 +00:00
|
|
|
for(const file of chunk.files) {
|
|
|
|
const extension = path.extname(file);
|
|
|
|
switch (extension) {
|
|
|
|
case ".js":
|
|
|
|
fileJs.push({
|
|
|
|
hash: chunk.hash,
|
|
|
|
file: file
|
2020-08-09 12:30:17 +00:00
|
|
|
});
|
2021-03-17 17:05:39 +00:00
|
|
|
break;
|
2020-08-09 12:30:17 +00:00
|
|
|
|
2021-03-17 17:05:39 +00:00
|
|
|
case ".css":
|
|
|
|
filesCss.push({
|
|
|
|
hash: chunk.hash,
|
|
|
|
file: file
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ".wasm":
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
throw "Unknown chunk file with extension " + extension;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(const module of compilation.chunkGraph.getChunkModules(chunk)) {
|
2021-03-23 11:03:00 +00:00
|
|
|
const identifier = module.identifier();
|
|
|
|
if(typeof identifier === "string" && identifier.startsWith("svg-sprites/")) {
|
2021-03-20 14:10:16 +00:00
|
|
|
/* custom svg sprite handler */
|
|
|
|
modules.push({
|
|
|
|
id: module.id,
|
|
|
|
context: "svg-sprites",
|
2021-03-23 11:03:00 +00:00
|
|
|
resource: identifier.substring("svg-sprites/".length)
|
2021-03-20 14:10:16 +00:00
|
|
|
});
|
2021-03-17 17:05:39 +00:00
|
|
|
continue;
|
|
|
|
}
|
2020-04-01 19:47:33 +00:00
|
|
|
|
2021-03-23 11:03:00 +00:00
|
|
|
if(!module.context) {
|
2021-03-17 17:05:39 +00:00
|
|
|
continue;
|
|
|
|
}
|
2020-04-01 19:47:33 +00:00
|
|
|
|
2021-03-23 11:03:00 +00:00
|
|
|
if(!module.type.startsWith("javascript/")) {
|
2021-03-17 17:05:39 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(module instanceof NormalModule)) {
|
|
|
|
continue;
|
2020-04-01 19:47:33 +00:00
|
|
|
}
|
|
|
|
|
2021-03-17 17:05:39 +00:00
|
|
|
if(module.resource.indexOf("webpack-dev-server") !== -1) {
|
|
|
|
/* Don't include dev server files */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(module.context !== path.dirname(module.resource)) {
|
|
|
|
throw "invalid context/resource relation (" + module.context + " <-> " + path.dirname(module.resource) + ")";
|
|
|
|
}
|
|
|
|
|
2021-03-23 11:03:00 +00:00
|
|
|
const moduleId = compilation.chunkGraph.getModuleId(module);
|
2021-03-17 17:05:39 +00:00
|
|
|
modules.push({
|
2021-03-20 14:10:16 +00:00
|
|
|
id: moduleId,
|
2021-03-17 17:05:39 +00:00
|
|
|
context: path.relative(this.options.context, module.context).replace(/\\/g, "/"),
|
|
|
|
resource: path.basename(module.resource)
|
|
|
|
});
|
|
|
|
}
|
2020-03-30 23:27:59 +00:00
|
|
|
}
|
|
|
|
|
2021-03-17 17:05:39 +00:00
|
|
|
chunkData[chunkGroup.options.name] = {
|
|
|
|
files: fileJs,
|
|
|
|
css_files: filesCss,
|
|
|
|
modules: modules
|
|
|
|
};
|
|
|
|
}
|
2021-03-17 12:28:27 +00:00
|
|
|
|
2021-03-17 17:05:39 +00:00
|
|
|
const payload = JSON.stringify({
|
|
|
|
version: 2,
|
|
|
|
chunks: chunkData
|
2020-03-30 23:27:59 +00:00
|
|
|
});
|
2021-03-17 17:05:39 +00:00
|
|
|
|
|
|
|
const fileName = this.options.outputFileName || "manifest.json";
|
|
|
|
compilation.emitAsset(fileName, new webpack.sources.RawSource(payload));
|
2020-03-30 23:27:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export = ManifestGenerator;
|