Files
starRiverProperty/frontend-source/scripts/unpack-webpack.js
T
反编译工作区 438a323038 feat(unpack-webpack): add webpack bundle unpacker script to frontend-source/scripts
Former-commit-id: 9b8bf61302736531deffa87de927f7d77a70ae0c
2026-04-29 11:49:31 +08:00

93 lines
2.7 KiB
JavaScript
Executable File

#!/usr/bin/env node
/**
* webpack bundle 解包器
* 识别 __webpack_modules__ 结构,按模块 ID 拆分为独立文件
*
* 用法: node unpack-webpack.js <bundle.js> <output-dir>
*/
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 <bundle.js> <output-dir>');
process.exit(1);
}
unpackWebpackBundle(args[0], args[1]);