@daqi/useless-files-webpack5-plugin
Version:
watch webpack project useless files
120 lines (111 loc) • 3.17 kB
JavaScript
const fs = require("fs");
const fg = require("fast-glob");
const path = require("path");
const shelljs = require("shelljs");
class CleanUnusedFilesW5Plugin {
constructor(options) {
this.opts = options;
}
apply(compiler) {
let _this = this;
if (compiler.plugin) {
compiler.plugin("after-emit", function (compilation, done) {
_this.findUnusedFiles(compilation, _this.opts);
done();
});
} else {
compiler.hooks.afterEmit.tap(
"CleanUnusedFilesW5Plugin",
(compilation) => {
_this.findUnusedFiles(compilation, _this.opts);
return true;
}
);
}
}
getDependFiles(compilation) {
return new Promise((resolve, reject) => {
const dependedFiles = [...compilation.fileDependencies].reduce(
(acc, usedFilepath) => {
if (!~usedFilepath.indexOf("node_modules")) {
acc.push(usedFilepath);
}
return acc;
},
[]
);
resolve(dependedFiles);
});
}
getAllFiles(pattern) {
return fg(pattern, {
nodir: true,
})
.then((files) => {
return files.map((item) => path.resolve(item));
})
.catch((err) => {
throw err;
});
}
dealExclude(paths, unusedList) {
paths = paths.map((p) => path.resolve(p));
const result = unusedList.filter((unused) => {
return !paths.includes(unused);
});
return result;
}
async findUnusedFiles(compilation, config = {}) {
const {
root = "./src",
clean = false,
output = "./unused-files.json",
exclude = false,
excludeSuffix = [],
} = config;
let pattern = Array.isArray(root)
? root.map((path) => path + "/**/*")
: [root + "/**/*"];
try {
const allChunks = await this.getDependFiles(compilation);
let getAllFiles = pattern.map((path) => this.getAllFiles(path));
let allFiles = await Promise.all(getAllFiles);
allFiles = allFiles.flat();
let unUsed = allFiles.filter((item) => {
let parse = path.parse(item);
let ext = parse.ext;
while (path.parse(parse.name).ext) {
parse = path.parse(parse.name);
ext = parse.ext + ext;
}
return !~allChunks.indexOf(item) && !excludeSuffix.includes(ext);
});
if (exclude && (typeof exclude === "string" || Array.isArray(exclude))) {
if (!Array.isArray(root)) {
root = [root];
}
let dealExclude = root
.map((path) => {
return exclude.map((excludeFile) => path + "/" + excludeFile);
})
.flat();
unUsed = this.dealExclude(dealExclude, unUsed);
}
if (typeof output === "string") {
fs.writeFileSync(output, JSON.stringify(unUsed, null, 4));
} else if (typeof output === "function") {
output(unUsed);
}
if (clean) {
unUsed.forEach((file) => {
shelljs.rm(file);
console.log(`remove file: ${file}`);
});
}
return unUsed;
} catch (err) {
throw err;
}
}
}
module.exports = CleanUnusedFilesW5Plugin;