为了防止项目被别人轻松抄袭,所以对代码的压缩、混淆还是很有必要的
一、常见插件介绍
这里我们使用 html-minifier(压缩html、css)、javascript-obfuscator(js混淆)
二、开始吧
const fs = require('fs');
const path = require('path');
const minify = require('html-minifier').minify;
const JO = require("javascript-obfuscator");
// 项目根目录
let sRootPath = 'ui'
fnTravel(sRootPath, fnCompressHtmlCss)
console.log("文件处理结束")
/**
* 遍历文件
* @params {*} dir 文件夹
* @params {*} callback 回调函数
*/
function fnTravel(dir, callback) {
// 同步读取指定目录的内容
let aFiles = fs.readdirSync(dir, 'utf8'), aFilterPath = ['.git', '.idea', 'html', 'README'];
aFiles.forEach((file) => {
// 获得完整路径
let pathname = path.join(dir, file)
// 判断是否处理
let bIsHandle = aFilterPath.some(item => pathname.includes(item));
if(!bIsHandle) {
// 同步获取详细信息
let stats = fs.statSync(pathname);
if (stats.isDirectory()) {
// 文件夹
fnTravel(pathname, callback)
} else {
// 文件
try {
if (pathname.endsWith('js')) {
// js 文件
fnObfuscatorJs(pathname)
} else {
// 其他文件
callback(pathname)
}
} catch (e) {
console.error("压缩失败:" + pathname);
console.error(e);
}
}
}
})
}
/**
* 压缩 html、css 文件方法
* @params {*} path 文件路径
*/
function fnCompressHtmlCss(path) {
let sTargetPath = path.replace('ui', 'dist'),
sCompressData = null, data = null;
if (!path.includes('img') && !path.includes('fonts')) {
// 获取文件内容
data = fs.readFileSync(path, 'utf8')
if(!path.endsWith('.min.css')) {
// 压缩后的文件内容
sCompressData = minify(data, {
collapseWhitespace: true, // 删除html里的空格 达到html的压缩
removeAttributeQuotes: true, // 尽可能删除html标签里的双引号 达到html的压缩
removeComments: true, //删除html中的注释
removeCommentsFromCDATA: true, //从脚本和样式删除的注释
minifyCSS: true, // 压缩css
})
}
}
let result = sCompressData ? sCompressData : data;
// 将数据同步写入文件
fnWriteFileRecursive(path, sTargetPath, result, (err) => {
if (err) console.error(err);
console.log('compress--[' + path + ']--success');
})
}
/**
* 压缩、混淆js方法
* @params {*} path 文件路径
*/
function fnObfuscatorJs(path) {
let sTargetPath = path.replace('ui', 'dist'),
sObfuscateCode = null;
// 获取文件内容
let data = fs.readFileSync(path, 'utf8')
if (!sTargetPath.endsWith('.min.js')) {
// 进行混淆
sObfuscateCode = JO.obfuscate(data, {
compact: true, // 压缩
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1,
numbersToExpressions: true,
simplify: true,
shuffleStringArray: true,
splitStrings: true,
stringArrayThreshold: 1,
});
}
// getObfuscatedCode() 返回混淆后的代码字符串,调用 toString 方法也会返回混淆代码
let sResultCode = sObfuscateCode ? sObfuscateCode.getObfuscatedCode() : data;
fnWriteFileRecursive(path, sTargetPath, sResultCode, (err) => {
if (err) console.error(err);
console.log('compress--[' + path + ']--success');
})
}
/**
* 创建目录并写入文件
* @params {*} sFromPath 来源路径
* @params {*} sTargetPath 目标路径
* @params {*} buffer 文件内容
* @params {*} callback 回调函数
* */
function fnWriteFileRecursive(sFromPath, sTargetPath, buffer, callback) {
let lastPath = sTargetPath.substring(0, sTargetPath.lastIndexOf("\\"));
// 创建目录
fs.mkdir(lastPath, {
recursive: true
}, (err) => {
if (err) return callback(err);
if (sTargetPath.includes('img') || sTargetPath.includes('fonts')) {
// 处理图片、字体文件
let readStream = fs.createReadStream(sFromPath); // 逐块读取文件
let writeStream = fs.createWriteStream(sTargetPath); // 对指定文件创建一个“可写数据流”
readStream.pipe(writeStream); // 将文件数据流导向 writeStream 对象
} else {
// 处理html、css、js文件
fs.writeFileSync(sTargetPath, buffer, function (err) {
if (err) return callback(err);
});
}
});
}
https://segmentfault.com/a/1190000040502426
https://blog.csdn.net/qq_37667074/article/details/108356269
https://blog.csdn.net/foupwang/article/details/103306332
https://blog.csdn.net/Liheishuai/article/details/124625069