@gforces/webpack-assets-map-plugin
Version:
Exports map of webpack compilation entrypoints and assets
78 lines (76 loc) • 2.93 kB
JavaScript
;
const fs = require('fs');
const path = require('path');
const defaultOptions = {
assets: true,
auxiliaryFiles: false,
clean: false,
entrypointsDependencies: true,
formatter: JSON.stringify,
output: 'assetsMap.json',
rootPath: ''
};
class AssetsMapPlugin {
constructor(options = {}) {
this.options = {
...defaultOptions,
...options
};
}
apply(compiler) {
this.compilerOutputPath = compiler.options.output.path || '';
this.options.rootPath = this.options.rootPath ? fs.realpathSync(this.options.rootPath) : this.compilerOutputPath;
compiler.hooks.afterEmit.tap('AssetsMapPlugin', compilation => {
const results = {
buildTime: 0,
entrypoints: {},
assets: {},
auxiliaryFiles: []
};
compilation.entrypoints.forEach(entrypoint => {
results.entrypoints[entrypoint.name] = [];
if (this.options.entrypointsDependencies) {
entrypoint.options.dependOn?.forEach(dependencyEntryPointName => {
results.entrypoints[entrypoint.name].push(...this.getEntryPointFiles(compilation.entrypoints.get(dependencyEntryPointName)));
});
}
results.entrypoints[entrypoint.name].push(...this.getEntryPointFiles(entrypoint));
});
compilation.assetsInfo.forEach((info, file) => {
if (info.sourceFilename) {
results.assets[info.sourceFilename] = this.relativePath(this.modulePath(file));
} else {
results.auxiliaryFiles.push(this.relativePath(this.modulePath(file)));
}
});
if (this.options.clean) {
const assets = [...Object.values(results.entrypoints).flat(), ...Object.values(results.assets), ...results.auxiliaryFiles].map(file => fs.realpathSync(`${this.options.rootPath}/${file}`));
const checkedPaths = [];
assets.forEach(asset => {
const dir = path.dirname(asset);
if (checkedPaths.includes(dir)) {
return;
}
checkedPaths.push(dir);
fs.readdirSync(dir, {
withFileTypes: true
}).filter(file => !(file.isDirectory() || assets.includes(`${dir}/${file.name}`))).forEach(file => fs.rmSync(`${dir}/${file.name}`));
});
}
results.buildTime = Date.now();
['assets', 'auxiliaryFiles'].forEach(option => !this.options[option] && delete results[option]);
const content = this.options.formatter(results);
fs.writeFileSync(this.options.output, content);
});
}
relativePath(file) {
return path.relative(this.options.rootPath, file);
}
modulePath(file) {
return fs.realpathSync(`${this.compilerOutputPath}/${file}`);
}
getEntryPointFiles(entryPoint) {
return [...entryPoint.chunks.reduce((files, chunk) => files.concat([...Array.from(chunk.files).map(file => this.relativePath(this.modulePath(file)))]), [])];
}
}
module.exports = AssetsMapPlugin;