From b81d004641c5de80e4b24f1251f1ed882027065c Mon Sep 17 00:00:00 2001 From: andrewlu Date: Thu, 4 Feb 2021 16:12:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E5=90=8E=E5=BB=B6=E8=BF=9F=E6=9B=B4=E6=96=B0=E5=BC=80=E5=85=B3?= =?UTF-8?q?.=20=E4=BD=BF=E7=94=A8=E6=AD=A4=E5=BC=80=E5=85=B3=E5=90=8E,?= =?UTF-8?q?=E6=B8=B8=E6=88=8F=E5=8C=85=E5=B0=86=E5=9C=A8=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E8=BF=9B=E5=85=A5=E6=B8=B8=E6=88=8F=E5=90=8E=E6=89=8D=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E6=9B=B4=E6=96=B0=E4=BF=A1=E6=81=AF,=20=E7=9B=B4?= =?UTF-8?q?=E5=88=B0=E9=87=8D=E5=90=AF=E5=90=8E=E5=86=8D=E6=89=93=E5=BC=80?= =?UTF-8?q?=E6=B8=B8=E6=88=8F=E6=89=8D=E5=BA=94=E7=94=A8=E6=9B=B4=E6=96=B0?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 优化热更流程,可以在构建完成后,再领奖注入热更,上传更新. --- packages/update-manager/js/FileUploader.js | 3 + packages/update-manager/js/FileUtils.js | 15 +- packages/update-manager/lib/UpdateManager.js | 129 ------------------ .../update-manager/lib/UpdateManager.js.meta | 9 -- packages/update-manager/main.js | 72 ++++++---- packages/update-manager/package.json | 9 -- packages/update-manager/panel/index.html | 53 ++++--- packages/update-manager/templates/pre_main.js | 55 +++++++- 8 files changed, 141 insertions(+), 204 deletions(-) delete mode 100644 packages/update-manager/lib/UpdateManager.js delete mode 100644 packages/update-manager/lib/UpdateManager.js.meta diff --git a/packages/update-manager/js/FileUploader.js b/packages/update-manager/js/FileUploader.js index 41ed34e..e332e5a 100644 --- a/packages/update-manager/js/FileUploader.js +++ b/packages/update-manager/js/FileUploader.js @@ -112,6 +112,9 @@ class FileUploader { this.queue.push({src: i, dst: (remoteStr + i.substring(startIndex)).replace(/\\/g, '/')}); } } + + logger.info('待上传文件数量:', this.queue.length); + this.checkUpload(); } diff --git a/packages/update-manager/js/FileUtils.js b/packages/update-manager/js/FileUtils.js index 6992f07..c815938 100644 --- a/packages/update-manager/js/FileUtils.js +++ b/packages/update-manager/js/FileUtils.js @@ -34,21 +34,22 @@ class FileUtil { * @param src * @param dst */ - async copy(src, dst) { + copy(src, dst) { const st = fs.statSync(src); if (st.isFile()) { - const readable = fs.createReadStream(src);//创建读取流 - const writable = fs.createWriteStream(dst);//创建写入流 - readable.pipe(writable); + const data = fs.readFileSync(src); + fs.writeFileSync(dst, data); return; } + if (!fs.existsSync(dst)) { fs.mkdirSync(dst, {recursive: true}); } + //读取目录 - const paths = fs.readdirSync(src); - for (let path of paths) { - this.copy(src + '/' + path, dst + '/' + path); + const files = fs.readdirSync(src); + for (let p of files) { + this.copy(src + path.sep + p, dst + path.sep + p); } }; diff --git a/packages/update-manager/lib/UpdateManager.js b/packages/update-manager/lib/UpdateManager.js deleted file mode 100644 index cb5be34..0000000 --- a/packages/update-manager/lib/UpdateManager.js +++ /dev/null @@ -1,129 +0,0 @@ -/** - * 方便直接获取当前版本号等信息. - * 使用方式: - * // @ts-ignore - * import UpdateManager = require( "UpdateManager"); - * 然后在代码中直接使用即可. - */ -class UpdateManager { - - cur_ver_code = 0; - cur_ver_name = "1.0.1"; - cur_ver_desc = ""; - ver_type = "dev"; - - new_ver_code = 0; - new_ver_name = "1.0.1"; - new_ver_desc = ""; - new_ver_info = {}; - - // 记录当前版本的bundles. 如果有新版本, 则自动下载新bundles. - cur_bundles = {}; - - updateSuccess = "0"; - - constructor() { - const curVer = window.localStorage.getItem("cur_ver_info"); - if (curVer) { - const verInfo = JSON.parse(curVer); - this.new_ver_code = this.cur_ver_code = verInfo.versionCode; - this.new_ver_name = this.cur_ver_name = verInfo.versionName; - this.ver_type = verInfo.versionType; - this.new_ver_desc = this.cur_ver_desc = verInfo.versionLog; - this.new_ver_info = verInfo; - this.cur_bundles = verInfo.bundleVers; - } - - this.updateSuccess = window.localStorage.getItem("ver_updated") || 0; - this.fetchNewVerInfo(); - } - - // 此方法适用于非强制更新包. 需要设计信息界面,显示版本信息. - // 手动调用进行更新下载, 下载完成返回true, 此时需要重启游戏才能应用更新. 需要界面提示用户. - doUpdate() { - if (this.hasNewVersion()) { - window.localStorage.setItem('cur_ver_info', JSON.stringify(this.new_ver_info)); - return true; - } - return false; - } - - resetUpdateFlag() { - window.localStorage.setItem('ver_updated', '0'); - } - - getUpdateFlag() { - return this.updateSuccess == 1; - } - - // 检测是否有新版本. - hasNewVersion() { - return this.new_ver_info && this.new_ver_info.versionCode && this.new_ver_info.versionCode != this.cur_ver_code; - } - - fetchNewVerInfo() { - let url = window.updateUrl || false; - if (!url) { - return; - } - // 游戏启动后再请求更新,避免影响启动速度. - url += `?_t=${Math.random()}`; - cc.log("请求更新地址:", url); - this._get(url).then(version => { - if (!version) { - console.log("未检测到更新版本内容"); - return; - } - if (version) { - cc.log('当前版本号:', this.cur_ver_code, this.cur_ver_name); - cc.log('请求更新内容:', version); - let verInfo = version; - if (typeof version === 'string') { - verInfo = JSON.parse(version); - } - this.new_ver_code = verInfo.versionCode; - this.new_ver_name = verInfo.versionName; - this.new_ver_desc = verInfo.versionLog; - - this.new_ver_info = verInfo; - - // 如果首次运行,本地未缓存版本信息,则进行缓存. - if (!this.cur_ver_code) { - cc.log("当前首次运行,记录版本信息"); - window.localStorage.setItem('cur_ver_info', JSON.stringify(this.new_ver_info)); - - this.new_ver_code = this.cur_ver_code = verInfo.versionCode; - this.new_ver_name = this.cur_ver_name = verInfo.versionName; - this.ver_type = verInfo.versionType; - this.new_ver_desc = this.cur_ver_desc = verInfo.versionLog; - - } else if (this.hasNewVersion() && verInfo.forceUpdate) { - window.localStorage.setItem('cur_ver_info', JSON.stringify(this.new_ver_info)); - window.localStorage.setItem('ver_updated', '1'); - cc.log("有新版本,且默认强制更新"); - } - } - }); - } - - // ajax 请求. - _get(url) { - return new Promise(resolve => { - const ajax = new XMLHttpRequest(); - ajax.open("get", url, true); - ajax.setRequestHeader("Content-Type", "application/json;charset=utf-8"); - ajax.onreadystatechange = function () { - if (ajax.readyState == 4) { - if (ajax.status == 200) { - resolve(ajax.responseText); - } else { - resolve(null); - } - } - } - ajax.send(null); - }); - } -} - -module.exports = new UpdateManager(); \ No newline at end of file diff --git a/packages/update-manager/lib/UpdateManager.js.meta b/packages/update-manager/lib/UpdateManager.js.meta deleted file mode 100644 index 7104b18..0000000 --- a/packages/update-manager/lib/UpdateManager.js.meta +++ /dev/null @@ -1,9 +0,0 @@ -{ - "ver": "1.0.8", - "uuid": "aa7483f4-ac0c-4809-9c5e-4e5734a26db6", - "isPlugin": false, - "loadPluginInWeb": true, - "loadPluginInNative": true, - "loadPluginInEditor": false, - "subMetas": {} -} \ No newline at end of file diff --git a/packages/update-manager/main.js b/packages/update-manager/main.js index b0c3d9c..6023d7f 100644 --- a/packages/update-manager/main.js +++ b/packages/update-manager/main.js @@ -1,35 +1,20 @@ 'use strict'; const fs = require('fs'); -const {join} = require('path'); +const path = require('path'); const FileUtil = require('./js/FileUtils'); const FileUpload = require('./js/FileUploader'); const logger = require('./js/logger'); -// 生成更新文件. +// 编译完成仅保存每次生成的bundleVers. 之后注入热更阶段再合并. const doMakeUpdatePackage = function (opt, cb) { if (opt.platform == 'android' || opt.platform == 'ios') { try { - const configStr = fs.readFileSync( - Editor.url('packages://update-manager/.settings.conf'), 'utf-8'); - const configJson = JSON.parse(configStr || "{}"); - if (typeof configJson.versionCfg.versionCode === 'undefined') { - logger.warn("未配置更新版本,不生成热更Patch"); - cb && cb(); - return; - } - if (!configJson.versionCfg.versionType || configJson.versionCfg.versionType.length <= 0) { - configJson.versionCfg.versionType = 'dev'; - } - const bundleVers = {}; for (let b of opt.bundles) { bundleVers[b.name] = b.version; } - saveNewVersionInfo(opt, bundleVers, configJson); - - const remoteDir = join(opt.dest, 'remote'); - const assetDir = join(opt.dest, 'assets'); - FileUtil.copy(assetDir, remoteDir); + let targetUpdatePath = path.join(opt.dest, `remote/bundleVers.json`); + FileUtil.write(targetUpdatePath, JSON.stringify(bundleVers)); cb && cb(); } catch (e) { @@ -41,20 +26,44 @@ const doMakeUpdatePackage = function (opt, cb) { } }; -const saveNewVersionInfo = function (opt, bundleVers, configJson) { +const getConfigJson = function () { + const configStr = fs.readFileSync( + Editor.url('packages://update-manager/.settings.conf'), 'utf-8'); + const configJson = JSON.parse(configStr || "{}"); + if (typeof configJson.versionCfg.versionCode === 'undefined') { + logger.warn("未配置更新版本,不生成热更Patch"); + return null; + } + if (!configJson.versionCfg.versionType || configJson.versionCfg.versionType.length <= 0) { + configJson.versionCfg.versionType = 'dev'; + } + return configJson; +}; + +// 注入热更信息. +const updateHotFixInfo = function () { + const configJson = getConfigJson(); + if (!configJson) return; + + const bundleVers = path.join(Editor.Project.path, `build/jsb-link/remote/bundleVers.json`); + if (!fs.existsSync(bundleVers)) { + logger.warn('未找到编译信息,请先构建项目.'); + return; + } + const bundles = JSON.parse(fs.readFileSync(bundleVers, 'utf-8')); + const data = { versionCode: configJson.versionCfg.versionCode, versionName: configJson.versionCfg.versionName, versionType: configJson.versionCfg.versionType, versionLog: configJson.versionCfg.versionLog, forceUpdate: configJson.versionCfg.forceUpdate, - server: `${configJson.versionCfg.baseUrl}${configJson.ftpCfg.rootPath}${configJson.versionCfg.versionType}/${configJson.versionCfg.versionCode}` + server: `${configJson.versionCfg.baseUrl}${configJson.ftpCfg.rootPath}${configJson.versionCfg.versionType}/${configJson.versionCfg.versionCode}`, + bundles: bundles }; - const updateInfo = Object.assign(data, {bundles: bundleVers}); - // 将版本更新信息写入文件 - let targetUpdatePath = join(opt.dest, `remote/update-${configJson.versionCfg.versionType}.json`) - FileUtil.write(targetUpdatePath, JSON.stringify(updateInfo, null, 2)); - logger.log("更新信息存储位置:", targetUpdatePath); + + let targetUpdatePath = path.join(Editor.Project.path, `build/jsb-link/remote/update-${configJson.versionCfg.versionType}.json`); + FileUtil.write(targetUpdatePath, JSON.stringify(data, null, 2)); }; module.exports = { @@ -94,8 +103,17 @@ module.exports = { 'open'() { Editor.Panel.open('update-manager'); }, + 'saveConfig'() { + // 上传更新包前,更新一次热更描述文件. + logger.info('生成热更文件...'); + updateHotFixInfo(); + logger.info('准备remote 资源...'); + const remoteDir = path.join(Editor.Project.path, 'build/jsb-link/remote'); // remote 目录. + const assetDir = path.join(Editor.Project.path, 'build/jsb-link/assets'); // assets目录. + FileUtil.copy(assetDir, remoteDir); + logger.info('remote 资源准备完毕,可以开始上传...'); + }, 'upload'(event, dir, dst, options) { - logger.info('upload....'); this.ftp.setOption(options, options.maxThread); this.ftp.upload(dir, dst); }, diff --git a/packages/update-manager/package.json b/packages/update-manager/package.json index 88d56e3..5e13ce5 100644 --- a/packages/update-manager/package.json +++ b/packages/update-manager/package.json @@ -9,15 +9,6 @@ "message": "update-manager:open" } }, - "runtime-resource": { - "path": "./lib", - "name": "lib" - }, - "reload": { - "ignore": [ - "lib/**/*" - ] - }, "panel": { "main": "panel/index.html", "type": "simple", diff --git a/packages/update-manager/panel/index.html b/packages/update-manager/panel/index.html index be79522..534c216 100644 --- a/packages/update-manager/panel/index.html +++ b/packages/update-manager/panel/index.html @@ -35,6 +35,13 @@ active-color="#13ce66" inactive-color="#ff4949" style="margin-right: 20px;"> + +
开启时后续更新包将在游戏启动后静默请求更新
否则将在启动时立即请求更新,然后才进入游戏.
+ +
@@ -168,7 +175,7 @@ - 保存配置信息 + 注入热更配置 上传更新包 @@ -201,7 +208,7 @@ versionLog: "", baseUrl: "", forceUpdate: true, // 强制静默更新. - // updateMoment: true // 启动时直接请求更新. + updateBefore: true // 启动时直接请求更新. }, ftpCfg: { host: "127.0.0.1", @@ -268,9 +275,21 @@ this.ftpCfg.rootPath += "/"; } const data = Object.assign({}, {versionCfg: this.versionCfg, ftpCfg: this.ftpCfg}); - fs && fs.writeFileSync && fs.writeFileSync( + fs.writeFileSync( Editor.url('packages://update-manager/.settings.conf'), JSON.stringify(data, null, 2), 'utf-8'); - this.$message({message: "配置保存成功!", type: "success"}); + + Editor.Ipc.sendToMain('update-manager:saveConfig'); + + let filePath = `update-${this.versionCfg.versionType}.json`; + const uploadDstPath = `${this.ftpCfg.rootPath}${this.versionCfg.versionType}/${filePath}`; + let updateUrl = `${this.versionCfg.baseUrl}${uploadDstPath}`; + const serverUrl = `${this.versionCfg.baseUrl}${this.ftpCfg.rootPath}${this.versionCfg.versionType}/${this.versionCfg.versionCode}`; + + if (this.notifyMainJs(updateUrl, serverUrl, this.versionCfg.updateBefore)) { + this.$message.info('热更注入成功'); + } else { + this.$message.error('热更注入失败,请检查构建目录.'); + } }, onUpload() { if (this.uploadState) { @@ -280,28 +299,17 @@ } this.uploadState = true; - logger.info("准备上传更新包"); this.$message("准备上传更新包"); - if (!this.versionCfg.baseUrl.endsWith('/') && this.versionCfg.baseUrl.length > 0) { - this.versionCfg.baseUrl += "/"; - } - if (!this.ftpCfg.rootPath.endsWith('/') && this.ftpCfg.rootPath.length > 0) { - this.ftpCfg.rootPath += "/"; - } - - let filePath = `update-${this.versionCfg.versionType}.json`; - const uploadDstPath = `${this.ftpCfg.rootPath}${this.versionCfg.versionType}/${filePath}`; - let updateUrl = `${this.versionCfg.baseUrl}${uploadDstPath}`; - const serverUrl = `${this.versionCfg.baseUrl}${this.ftpCfg.rootPath}${this.versionCfg.versionType}/${this.versionCfg.versionCode}`; - - if (!this.notifyMainJs(updateUrl, serverUrl)) { - return; - } if (this.ftpCfg.onlyJson) { logger.warn('当前仅上传JSON文件,请手动上传remote目录'); return; } + + const filePath = `update-${this.versionCfg.versionType}.json`; + const uploadDstPath = `${this.ftpCfg.rootPath}${this.versionCfg.versionType}/${filePath}`; + logger.info('上传文件:', uploadDstPath); + // 上传更新描述文件. const updateJsonPath = path.join(this.projectPath, `build/jsb-link/remote/${filePath}`); Editor.Ipc.sendToMain('update-manager:upload', updateJsonPath, uploadDstPath, this.ftpCfg); @@ -324,7 +332,7 @@ self.uploadState = !args; }); }, - notifyMainJs(updateUrl, serverUrl) { + notifyMainJs(updateUrl, serverUrl, updateBefore) { this.$message.info("notifyMainJs"); const filePath = path.join(this.projectPath, 'build/jsb-link/main.js'); const exists = fs.existsSync(filePath); @@ -335,12 +343,13 @@ let mainjs = fs.readFileSync(filePath, 'utf-8'); let varJs = `window.updateUrl="${updateUrl}";\r\n`; let remoteJs = `window.remoteUrl="${serverUrl}";\r\n`; + let updateBeforeFlag = `window.updateBefore=${updateBefore};\r\n`; // preMainJS read. const preMain = fs && fs.readFileSync && fs.readFileSync( Editor.url('packages://update-manager/templates/pre_main.js'), 'utf-8'); if (!mainjs.startsWith(varJs)) { mainjs = mainjs.replace('window.boot();', 'window.beforeBoot();'); - mainjs = varJs + remoteJs + preMain + mainjs; + mainjs = varJs + remoteJs + updateBeforeFlag + preMain + mainjs; fs && fs.writeFileSync && fs.writeFileSync(filePath, mainjs, 'utf-8'); } this.$message.success("Main.js 热更代码注入成功"); diff --git a/packages/update-manager/templates/pre_main.js b/packages/update-manager/templates/pre_main.js index 83cdce6..2aff676 100644 --- a/packages/update-manager/templates/pre_main.js +++ b/packages/update-manager/templates/pre_main.js @@ -1,4 +1,5 @@ window.beforeBoot = function () { + // console.log("游戏正在启动中.") if (window.remoteUrl) { const settings = window._CCSettings; @@ -11,16 +12,51 @@ window.beforeBoot = function () { window.boot(); return; } + // 游戏启动后再请求更新,避免影响启动速度. + url += `?_t=${Math.random()}`; + cc.log("请求更新地址:", url); + if (window.updateBefore) { + _get(url).then(resp => { + if (!resp) { + window.boot(); + return; + } + window.localStorage.setItem('cur_ver_info', resp); + window.onBooting(); + }); + } else { + window.onBooting(); + _get(url).then(resp => { + if (!resp) { + return; + } + window.localStorage.setItem('cur_ver_info', resp); + }); + } +}; +window.onBooting = function () { // 请求缓存信息,判断是否需要更新. let assetStr = window.localStorage.getItem('cur_ver_info'); if (!assetStr) { window.boot(); } else { - // console.log("当前版本信息:", assetStr); + console.log("当前版本信息:", assetStr); let asset = JSON.parse(assetStr); window.mergeVersion(asset); window.boot(); + + // 判断当前是否有版本更新. + const lastVer = window.localStorage.getItem('last_ver_code') || asset.versionCode; + const curVer = asset.versionCode || 0; + if (lastVer != curVer) { + window.localStorage.setItem('new_ver_flag', "1"); + } else { + window.localStorage.setItem('new_ver_flag', "0"); + } + window.localStorage.setItem('last_ver_code', curVer); + // 当前版本名称. + window.localStorage.setItem('cur_ver_name', asset.versionName); } }; window.mergeVersion = function (updateInfo) { @@ -41,3 +77,20 @@ window.mergeVersion = function (updateInfo) { } }; +function _get(url) { + return new Promise(resolve => { + const ajax = new XMLHttpRequest(); + ajax.open("get", url, true); + ajax.setRequestHeader("Content-Type", "application/json;charset=utf-8"); + ajax.onreadystatechange = function () { + if (ajax.readyState == 4) { + if (ajax.status == 200) { + resolve(ajax.responseText); + } else { + resolve(null); + } + } + } + ajax.send(null); + }); +}; \ No newline at end of file