#!/usr/bin/env node /** * webpack bundle 解包器 * 识别 __webpack_modules__ 结构,按模块 ID 拆分为独立文件 * * 用法: node unpack-webpack.js */ const fs = require('fs'); const path = require('path'); function unpackWebpackBundle(bundlePath, outputDir) { const code = fs.readFileSync(bundlePath, 'utf-8'); let modules = null; // 模式1: __webpack_modules__ = { 123: function(module, exports, __webpack_require__) {...}, ... } const modulesAssignMatch = code.match(/__webpack_modules__\s*=\s*(\{[\s\S]*?\});/); // 模式2: (function(modules) { ... })({ 123: function(...) {...}, ... }) const iifeMatch = code.match(/\(function\(\s*\w+\s*\)\s*\{[\s\S]*?\}\s*\)\s*\(\s*(\{[\s\S]*?\})\s*\)\s*;/); if (modulesAssignMatch) { modules = eval('(' + modulesAssignMatch[1] + ')'); } else if (iifeMatch) { modules = eval('(' + iifeMatch[1] + ')'); } else { console.error('未识别到 webpack 模块结构,尝试按 function(module, exports) 正则提取'); modules = extractByRegex(code); } if (!modules || Object.keys(modules).length === 0) { console.error('未能提取任何模块'); process.exit(1); } fs.mkdirSync(outputDir, { recursive: true }); let count = 0; for (const [id, factory] of Object.entries(modules)) { const moduleCode = typeof factory === 'function' ? factory.toString() : JSON.stringify(factory, null, 2); const safeId = String(id).replace(/[^a-zA-Z0-9_-]/g, '_'); fs.writeFileSync(path.join(outputDir, `module_${safeId}.js`), moduleCode); count++; } console.log(`拆解完成: ${count} 个模块 → ${outputDir}`); return count; } function extractByRegex(code) { const modules = {}; const re = /(\d+):\s*function\s*\(\s*\w+\s*,\s*\w+\s*,\s*\w+\s*\)\s*\{/g; let match; const matches = []; while ((match = re.exec(code)) !== null) { matches.push({ id: match[1], start: match.index }); } for (let i = 0; i < matches.length; i++) { const current = matches[i]; const next = matches[i + 1]; const startIdx = current.start; const endIdx = next ? next.start : code.length; let depth = 1; let pos = startIdx + current[0].length; while (depth > 0 && pos < endIdx) { if (code[pos] === '{') depth++; if (code[pos] === '}') depth--; pos++; } const funcBody = code.substring(startIdx, pos); modules[current.id] = funcBody; } return modules; } // CLI const args = process.argv.slice(2); if (args.length < 2) { console.log('用法: node unpack-webpack.js '); process.exit(1); } unpackWebpackBundle(args[0], args[1]);