const fs = require('fs'); const path = require('path'); const { exec } = require('child_process'); const { minify } = require('terser'); // 源目录和目标目录 const sourceDir = path.join(__dirname, 'dist', 'ts'); const jsSourceDir = path.join(__dirname, 'src', 'js'); const targetDir = path.join(__dirname, 'dist', 'compressed'); const tsSourceDir = path.join(__dirname, 'src', 'ts'); // 确保目标目录存在 if (!fs.existsSync(targetDir)) { fs.mkdirSync(targetDir, { recursive: true }); } // 递归获取所有JS文件 function getAllJsFiles(dir, fileList = []) { console.log(`正在扫描目录: ${dir}`); if (!fs.existsSync(dir)) { console.log(`目录不存在: ${dir}`); return fileList; } const files = fs.readdirSync(dir); console.log(`发现文件: ${files.length}个`); files.forEach(file => { const filePath = path.join(dir, file); const stat = fs.statSync(filePath); if (stat.isDirectory()) { getAllJsFiles(filePath, fileList); } else if (file.endsWith('.js') && !file.endsWith('.compressed.js')) { console.log(`添加文件: ${filePath}`); fileList.push(filePath); } }); return fileList; } // 获取所有需要处理的JS文件 function getJsFilesToProcess() { console.log('开始获取需要处理的文件...'); console.log(`jsSourceDir: ${jsSourceDir}`); if (shouldCompileTs) { console.log('处理所有文件模式'); // 获取编译后的TypeScript文件 const tsCompiledFiles = getAllJsFiles(sourceDir); console.log(`找到 ${tsCompiledFiles.length} 个TS编译文件`); // 获取js目录下的所有JS文件 const pureJsFiles = getAllJsFiles(jsSourceDir); console.log(`找到 ${pureJsFiles.length} 个纯JS文件`); return [...tsCompiledFiles, ...pureJsFiles]; } else { console.log('仅处理JS文件模式'); // 只处理js目录下的文件 const jsFiles = getAllJsFiles(jsSourceDir); console.log(`找到 ${jsFiles.length} 个JS文件`); return jsFiles; } } // 处理每个文件 async function processFiles() { console.log('开始处理文件...'); const jsFiles = getJsFilesToProcess(); console.log(`总共找到 ${jsFiles.length} 个文件需要处理`); for (const file of jsFiles) { // 确定文件来源(ts编译或js目录) const isFromTs = file.includes(path.sep + 'dist' + path.sep + 'ts' + path.sep); const baseSourceDir = isFromTs ? sourceDir : jsSourceDir; const relativePath = path.relative(baseSourceDir, file); const targetPath = path.join(targetDir, relativePath); // 确保目标文件夹存在 const targetDirPath = path.dirname(targetPath); if (!fs.existsSync(targetDirPath)) { fs.mkdirSync(targetDirPath, { recursive: true }); } console.log(`处理文件: ${relativePath}`); try { // 读取源文件 const code = fs.readFileSync(file, 'utf8'); // 混淆选项 const options = { compress: { drop_console: true, // 删除console.*调用 drop_debugger: true, // 删除debugger语句 dead_code: true, // 删除无法访问的代码 unused: true, // 删除未使用的变量和函数 join_vars: true // 合并连续变量声明 }, output: { comments: false, // 删除所有注释 beautify: false, // 不美化输出 indent_level: 0, // 不缩进 ascii_only: true // 仅使用ASCII字符 } }; // 执行混淆 const result = await minify(code, options); // 写入目标文件 fs.writeFileSync(targetPath, result.code, 'utf8'); console.log(`成功处理: ${relativePath} -> ${path.basename(targetPath)}`); } catch (error) { console.error(`处理 ${relativePath} 时出错:`, error); } } console.log('所有文件处理完成!'); } // 根据命令行参数决定执行流程 const args = process.argv.slice(2); const shouldCompileTs = !args.includes('--js-only'); if (shouldCompileTs) { // 执行 TypeScript 编译和混淆 console.log('开始 TypeScript 编译...'); exec('npx tsc --project tsconfig.json --skipLibCheck', (error, stdout, stderr) => { if (error) { console.error(`编译错误: ${error.message}`); console.error(`错误详情: ${stdout}`); return; } if (stderr) { console.error(`编译警告: ${stderr}`); } console.log('TypeScript 编译完成!'); processFiles(); }); } else { // 只执行 JavaScript 混淆 console.log('跳过 TypeScript 编译,只处理 JavaScript 文件...'); processFiles(); }