Skip to content

建义把index.js拆分了 #23

Description

@yxopen

const fs = require('fs');
const pathUtils = require('path');
const { parse } = require('@babel/parser');
const { default: traverse } = require('@babel/traverse');
const { default: generate } = require('@babel/generator');

// ==========================================
// 1. 配置路径
// ==========================================
const filePath = 'D:\游戏\cocos\wechatgame_\assets\main\index.js';
const directoryPath = pathUtils.join(pathUtils.dirname(filePath), 'out');

if (!fs.existsSync(directoryPath)) {
fs.mkdirSync(directoryPath, { recursive: true });
}

// ==========================================
// 2. 内置 Cocos Creator UUID 解压工具
// ==========================================
const BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
const BASE64_VALUES = new Array(123);
for (let i = 0; i < BASE64_CHARS.length; i++) {
BASE64_VALUES[BASE64_CHARS.charCodeAt(i)] = i;
}
const HexChars = '0123456789abcdef'.split('');

function decompressUuid(uuid) {
if (!uuid || uuid.length !== 22) {
return uuid;
}
let res = [];
let i = 0;
let j = 0;
while (i < 22) {
let b1 = BASE64_VALUES[uuid.charCodeAt(i++)];
let b2 = BASE64_VALUES[uuid.charCodeAt(i++)];
let b3 = BASE64_VALUES[uuid.charCodeAt(i++)];
let b4 = BASE64_VALUES[uuid.charCodeAt(i++)];

let d1 = (b1 << 2) | (b2 >> 4);
let d2 = ((b2 & 15) << 4) | (b3 >> 2);
let d3 = ((b3 & 3) << 6) | b4;

res[j++] = HexChars[d1 >> 4]; res[j++] = HexChars[d1 & 15];
res[j++] = HexChars[d2 >> 4]; res[j++] = HexChars[d2 & 15];
res[j++] = HexChars[d3 >> 4]; res[j++] = HexChars[d3 & 15];

}

let str = res.join('');
return str.slice(0, 8) + '-' + str.slice(8, 12) + '-' + str.slice(12, 16) + '-' + str.slice(16, 20) + '-' + str.slice(20, 32);
}

// ==========================================
// 3. 核心处理逻辑 (完美修复版)
// ==========================================
function separateFunctionsInFile(filePath) {
const fileContent = fs.readFileSync(filePath, 'utf8');
const ast = parse(fileContent, { sourceType: 'module' });

// 1. 最外层全局遍历
traverse(ast, {
ObjectProperty(path) {
const { node } = path;
if (
node.value.type === 'ArrayExpression' &&
node.value.elements.length > 0 &&
node.value.elements[0].type === 'FunctionExpression'
) {
let funcName = '';
if (node.key.type === 'Identifier') funcName = node.key.name;
else if (node.key.type === 'StringLiteral') funcName = node.key.value;

    if (funcName) {
      const funcNode = node.value.elements[0];
      let extractedUuid = null;
      const param1 = funcNode.params[0] ? funcNode.params[0].name : 'require';

      // 2. 对当前这个对象节点进行局部向下扫描,完美规避独立 traverse 报错,也不会误跳过
      path.traverse({
        CallExpression(innerPath) {
          const innerNode = innerPath.node;

          // 提取 UUID 并移除 cc._RF.push
          if (
            innerNode.callee.type === 'MemberExpression' &&
            innerNode.callee.object.type === 'MemberExpression' &&
            innerNode.callee.object.object.name === 'cc' &&
            innerNode.callee.object.property.name === '_RF'
          ) {
            if (innerNode.arguments.length >= 2 && innerNode.arguments[1].type === 'StringLiteral') {
              extractedUuid = innerNode.arguments[1].value; // 抓取到了 UUID
            }
            if (innerPath.parentPath.isExpressionStatement()) {
              innerPath.parentPath.remove();
            } else {
              innerPath.remove();
            }
            return;
          }

          // 修改 require 路径
          if (
            innerNode.callee.type === 'Identifier' &&
            innerNode.callee.name === param1 &&
            innerNode.arguments.length === 1 &&
            innerNode.arguments[0].type === 'StringLiteral'
          ) {
            const requirePath = innerNode.arguments[0].value;
            innerNode.arguments[0].value = pathUtils.basename(requirePath);
          }
        },

        // 处理特殊字符串
        StringLiteral(innerPath) {
          const innerNode = innerPath.node;
          if (innerNode.extra && innerNode.extra.raw && innerNode.extra.raw.includes('\\u')) {
            let value = innerNode.value;
            if (value.includes('\r') || value.includes('\n')) {
              value = value.replace(/\r/g, '\\r').replace(/\n/g, '\\n');
            }
            innerNode.extra.raw = `"${value}"`;
          }
        }
      });

      // 3. 将修改好的函数导出
      exportFunctionCode(funcNode, funcName, extractedUuid);
    }
  }
}

});
}

/**

  • 导出 JS 和 Meta
    */
    function exportFunctionCode(funcNode, funcName, extractedUuid) {
    const funcParams = funcNode.params.map((param) => param.name);
    const paramAssignments = funcParams
    .map((param, index) => {
    const assignment = index === 0 ? 'require' : index === 1 ? 'module' : 'exports';
    return var ${param} = ${assignment};;
    })
    .join('\n');

const bodyCode = funcNode.body.body.map((node) => generate(node).code).join('\n');
const modifiedCode = ${paramAssignments}\n${bodyCode};

const outJsPath = pathUtils.join(directoryPath, ${funcName}.js);
fs.writeFileSync(outJsPath, modifiedCode, 'utf8');

// 如果抓到了 UUID,就生成 Meta
if (extractedUuid) {
saveMeta(funcName, extractedUuid);
}
}

/**

  • 生成 Meta 文件实体
    */
    function saveMeta(funcName, uuidValue) {
    const deuuid = decompressUuid(uuidValue);
    const jsonData = {
    ver: '1.1.0',
    uuid: deuuid,
    importer: 'javascript',
    isPlugin: false,
    loadPluginInWeb: true,
    loadPluginInNative: true,
    loadPluginInEditor: false,
    subMetas: {},
    };

const jsonString = JSON.stringify(jsonData, null, 2);
const outMetaPath = pathUtils.join(directoryPath, ${funcName}.js.meta);
fs.writeFileSync(outMetaPath, jsonString, 'utf8');
}

// ==========================================
// 4. 执行
// ==========================================
separateFunctionsInFile(filePath);
console.log('✨ 导出成功!:', directoryPath);`

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions