@honor-minigame/cli
Version:
honor minigame pack cli
106 lines (95 loc) • 3.91 kB
JavaScript
import fs from 'fs-extra'
import path from 'path'
import { fileURLToPath } from 'url'
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
// CLI 自身 common 目录(修复文件源)
const COMMON_DIR = path.join(__dirname, '../common')
// cocos2.x 运行时崩溃修复文件(运行时 monkey-patch,不改引擎文件):
// image-load-fix.js —— 修复 internal://files/ 协议头图片加载 ERROR 4930(黑屏卡死)
// renderflow-fix.js —— 修复 RenderFlow _assembler 空引用崩溃
const COCOS2X_FIX_FILES = ['image-load-fix.js', 'renderflow-fix.js']
// boot.js 注入锚点:require('adapter/index.js'); 行
// 兼容行首缩进、单/双引号、可选分号、行尾注释及 \r\n 换行
const ADAPTER_INDEX_REQUIRE = /([ \t]*require\(\s*['"]adapter\/index\.js['"]\s*\)\s*;?[^\n]*\r?\n)/
/**
* 判断是否为 cocos2.x 游戏
* 与 utils/engineType.js 中 cocos2.x 判断一致:src/cocos2d-runtime.js 存在即 cocos2.x
* (cocos3.x 使用 src/settings.json 的 CocosEngine 字段,不会有 cocos2d-runtime.js)
* @param {string} rootPath 项目根目录
* @returns {boolean}
*/
function isCocos2x(rootPath) {
return fs.existsSync(path.join(rootPath, 'src', 'cocos2d-runtime.js'))
}
/**
* 定位项目中的 adapter 目录(包含 index.js 的那个)
* boot.js 中 require('adapter/index.js') 的解析位置,优先 src/adapter,回退项目根 adapter
* @param {string} rootPath 项目根目录
* @returns {string|null}
*/
function resolveAdapterDir(rootPath) {
const candidates = [
path.join(rootPath, 'src', 'adapter'),
path.join(rootPath, 'adapter')
]
for (const dir of candidates) {
if (fs.existsSync(path.join(dir, 'index.js'))) {
return dir
}
}
return null
}
/**
* cocos2.x 运行时崩溃适配注入
*
* 触发条件:cocos2.x 游戏(src/cocos2d-runtime.js 存在)且 src/boot.js 存在。
* 做两件事:
* 1. 将 common/image-load-fix.js、common/renderflow-fix.js 复制到 adapter/ 下;
* 2. 在 boot.js 的 require('adapter/index.js'); 下方追加这两个文件的 require。
*
* 两个修复文件内部均已用 cc.game.once(EVENT_GAME_INITED, apply) 兜底,
* 即便在 cocos2d-runtime.js 之前被 require,引擎初始化后仍会补 patch,故放在
* require('adapter/index.js') 下方是安全的。
*
* @param {string} rootPath 项目根目录
*/
export function injectCocos2xRuntimeFix(rootPath) {
if (!isCocos2x(rootPath)) {
return
}
const bootJsPath = path.join(rootPath, 'src', 'boot.js')
if (!fs.existsSync(bootJsPath)) {
return
}
const adapterDir = resolveAdapterDir(rootPath)
if (!adapterDir) {
console.warn('### HONOR PACK ### 未找到 adapter/index.js,跳过 cocos2.x 运行时修复注入')
return
}
// 1. 复制修复文件到 adapter 目录
COCOS2X_FIX_FILES.forEach((file) => {
const src = path.join(COMMON_DIR, file)
const dest = path.join(adapterDir, file)
fs.copySync(src, dest)
})
// 2. 在 boot.js 的 require('adapter/index.js'); 下方注入两个 require
let bootContent = fs.readFileSync(bootJsPath, 'utf8')
// 防重复:已注入则跳过
if (bootContent.indexOf("require('adapter/image-load-fix.js')") > -1) {
return
}
if (!ADAPTER_INDEX_REQUIRE.test(bootContent)) {
console.warn("### HONOR PACK ### boot.js 中未找到 require('adapter/index.js') 锚点,跳过注入")
return
}
bootContent = bootContent.replace(ADAPTER_INDEX_REQUIRE, (match) => {
// 继承锚点行的缩进,保持 boot.js 风格一致
const indent = (match.match(/^[ \t]*/) || [''])[0]
const injectLines =
`${indent}require('adapter/image-load-fix.js');\n` +
`${indent}require('adapter/renderflow-fix.js');\n`
return match + injectLines
})
fs.writeFileSync(bootJsPath, bootContent, 'utf8')
}