import JavaScriptObfuscator from 'javascript-obfuscator' import fs from 'fs' import path from 'path' import ignore from 'ignore' import { webVersion } from './env.js' // 导入 webVersion // 获取当前目录和构建目标目录 const sourceDir = path.dirname(new URL(import.meta.url).pathname) const distDir = path.join(sourceDir, 'dist') const gitignorePath = path.join(sourceDir, '.gitignore') // 定义需要排除的文件和文件夹 const excludedFilesAndDirs = [distDir, 'node_modules'] // 读取 .gitignore 文件并解析 const ig = ignore().add(fs.readFileSync(gitignorePath, 'utf-8')) // 创建目录 const createDir = dir => { if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }) } } // 修改 package.json 文件 const updatePackageJsonForWeb = () => { const packageJsonPath = path.join(sourceDir, 'package.json') const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')) packageJson.name = 'star-cloud-web' packageJson.main = './web/index.js' packageJson.version = webVersion fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)) console.log('Web build configuration updated in package.json!') } // 处理文件 const processFile = (filePath, targetPath) => { const code = fs.readFileSync(filePath, 'utf-8') if (!code.trim()) { console.log(`跳过空文件: ${filePath}`) return } try { const obfuscatedCode = JavaScriptObfuscator.obfuscate(code, { compact: true, controlFlowFlattening: true, deadCodeInjection: true, stringArray: true, stringArrayEncoding: ['base64'], stringArrayThreshold: 0.75 }).getObfuscatedCode() fs.writeFileSync(targetPath, obfuscatedCode) console.log(`混淆完成: ${filePath}`) } catch (error) { console.error(`混淆失败: ${filePath}`) console.error(error.message) } } // 遍历并处理文件 const traverseAndProcess = (currentDir, targetDir) => { createDir(targetDir) fs.readdirSync(currentDir).forEach(file => { const sourcePath = path.join(currentDir, file) const targetPath = path.join(targetDir, file) const stats = fs.statSync(sourcePath) // 如果是 node_modules 文件夹或者被 .gitignore 忽略的文件或文件夹,跳过 if ( sourcePath.includes('node_modules') || // 排除 node_modules 文件夹 ig.ignores(path.relative(sourceDir, sourcePath)) || // 过滤 .gitignore 忽略的文件 excludedFilesAndDirs.some(excludedPath => sourcePath.startsWith(excludedPath)) // 排除其他指定路径 ) { console.log(`跳过文件或文件夹: ${sourcePath}`) return } // 针对 web/index.js 文件,不进行混淆,直接复制到 dist 目录 if (sourcePath === path.join(sourceDir, 'web', 'index.js')) { console.log(`复制入口文件: ${sourcePath}`) fs.copyFileSync(sourcePath, targetPath) return } if (sourcePath === path.join(sourceDir, 'constant.js')) { console.log(`复制入口文件: ${sourcePath}`) fs.copyFileSync(sourcePath, targetPath) return } // 针对 web.md 文件,直接复制到 dist 目录,并重命名为 README.md if (sourcePath === path.join(sourceDir, 'web.md')) { console.log(`复制 web.md 文件并重命名为 README.md: ${sourcePath}`) const readmePath = path.join(targetDir, 'README.md') fs.copyFileSync(sourcePath, readmePath) return } // 对其他 JS 文件进行混淆 if (stats.isDirectory()) { traverseAndProcess(sourcePath, targetPath) } else if (sourcePath.endsWith('.js')) { processFile(sourcePath, targetPath) } else if (sourcePath.endsWith('.json')) { console.log(`跳过 JSON 文件: ${sourcePath}`) fs.copyFileSync(sourcePath, targetPath) } else { console.log(`跳过非 JS 文件: ${sourcePath}`) } }) } // 清理已存在的 dist 目录 if (fs.existsSync(distDir)) { fs.rmSync(distDir, { recursive: true, force: true }) } createDir(distDir) updatePackageJsonForWeb() // 在开始混淆前先修改 package.json traverseAndProcess(sourceDir, distDir) console.log('混淆完成,输出目录为 dist!')