takes in the stats object from a successful compilation and returns a manifest object that characterizes the results of the compilation for CSS/JS loading and integrity checking. the manifest has the following entries: jsChunksByName: an object that maps chunk names to their JS entrypoint file. cssChunksByName: an object that maps chunk names to their CSS file. Note that not all named chunks necessarily have a CSS file, so not all names will show up as a key in this object. jsChunksById: an object that maps chunk ids to their JS entrypoint file. hash: the overall hash of the build, which can be used to check integrity with prebuilt sources.
function statsToManifest(stats) {
	const jsChunksByName = {};
	const cssChunksByName = {};
	const jsChunksById = {};
	const cssChunksById = {};
	let file;
	for (const chunk of stats.compilation.chunks) {
		for (let i = 0; i < chunk.files.length; i++) {
			file = chunk.files[i];
			if (/\.css$/.test(file)) {
				cssChunksById[chunk.id] = file;
				if (chunk.name) {
					cssChunksByName[chunk.name] = file;
				}
			} else if (/^((?!hot-update).)*\.js$/.test(file)) {
				// Ensure we're building a manifest that includes the main JS bundle, not any simple hot updates
				jsChunksById[chunk.id] = file;
				if (chunk.name) {
					jsChunksByName[chunk.name] = file;
				}
			}
		}
	}
	return {
		jsChunksByName,
		jsChunksById,
		cssChunksByName,
		cssChunksById,
		hash: stats.hash,
	};
}