游戏热更新插件

This commit is contained in:
andrewlu
2021-02-02 00:11:00 +08:00
parent ba874af797
commit 3106b54566
40 changed files with 34326 additions and 37 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,266 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- import CSS -->
<link rel="stylesheet" href="./element-ui/index.css">
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #3646ea;
background-color: #fafcfc;
padding: 35px;
height: 100%;
}
</style>
</head>
<body style="height: 1000px;">
<div id="app">
<el-tabs v-model="tabName">
<el-tab-pane label="版本配置" name="versionConfig" style="height: 400px;">
<el-form ref="version" :model="versionCfg" label-width="100px">
<el-tooltip effect="dark" :content="tip.versionCode" open-delay=500 placement="top">
<el-form-item label="新版本号:">
<el-input type="number" v-model="versionCfg.versionCode" placeholder="1"></el-input>
</el-form-item>
</el-tooltip>
<el-tooltip effect="dark" :content="tip.versionName" open-delay=500 placement="top">
<el-form-item label="版本名称:">
<el-input v-model="versionCfg.versionName" placeholder="1.0.0"></el-input>
</el-form-item>
</el-tooltip>
<el-tooltip effect="dark" :content="tip.versionType" open-delay=500 placement="top">
<el-form-item label="版本类型:">
<el-input v-model="versionCfg.versionType" placeholder="dev"></el-input>
</el-form-item>
</el-tooltip>
<el-tooltip effect="dark" :content="tip.baseUrl" open-delay=500 placement="top">
<el-form-item label="热更地址:">
<el-input v-model="versionCfg.baseUrl"
placeholder="https://cdn-xxx.com"></el-input>
</el-form-item>
</el-tooltip>
<el-tooltip effect="dark" :content="tip.versionLog" open-delay=500 placement="top">
<el-form-item label="版本描述:">
<el-input type="textarea" v-model="versionCfg.versionLog"
placeholder="版本更新内容..."></el-input>
</el-form-item>
</el-tooltip>
</el-form>
</el-tab-pane>
<el-tab-pane label="上传配置" name="ftpConfig" style="height: 400px;">
<el-form ref="ftpCfg" :model="ftpCfg" label-width="100px">
<el-tooltip effect="dark" :content="tip.ip" placement="top" open-delay=500>
<el-form-item label="IP:">
<el-col :span="18">
<el-input type="text" v-model="ftpCfg.host" placeholder="127.0.0.1"></el-input>
</el-col>
<el-col class="line" :span="2">-</el-col>
<el-col :span="4">
<el-input type="number" v-model="ftpCfg.port" placeholder="端口号"></el-input>
</el-col>
</el-form-item>
</el-tooltip>
<el-tooltip effect="dark" :content="tip.user" open-delay=500 placement="top">
<el-form-item label="登录帐号:">
<el-col :span="11">
<el-input type="text" v-model="ftpCfg.user" placeholder="登录帐号"></el-input>
</el-col>
<el-col class="line" :span="2">-</el-col>
<el-col :span="11">
<el-input type="password" v-model="ftpCfg.password" placeholder="密码"></el-input>
</el-col>
</el-form-item>
</el-tooltip>
<el-tooltip effect="dark" content="FTP长连接持续心跳时间" open-delay=500 placement="top">
<el-form-item label="KeepAlive:">
<el-input type="number" v-model="ftpCfg.keepalive" placeholder="10000"></el-input>
</el-form-item>
</el-tooltip>
<el-tooltip effect="dark" content="FTP同时上传文件数,数量越大,上传效率越高<br/>受限于带宽性能,并非越大越好,推荐5~10" open-delay=500
placement="top">
<el-form-item label="并发数量:">
<el-input type="number" v-model="ftpCfg.maxThread" placeholder="5"></el-input>
</el-form-item>
</el-tooltip>
<el-tooltip effect="dark" :content="tip.rootPath" open-delay=500 placement="top">
<el-form-item label="FTP目录:">
<el-input v-model="ftpCfg.rootPath"
placeholder="TempDir/"></el-input>
</el-form-item>
</el-tooltip>
<el-tooltip effect="dark" content="勾选后仅会上传热更描述文件,<br/>需要手动上传remote目录" open-delay=500 placement="top">
<el-form-item label="手动上传:">
<el-switch v-model="ftpCfg.onlyJson"></el-switch>
</el-form-item>
</el-tooltip>
</el-form>
</el-tab-pane>
<el-tab-pane label="使用帮助" name="help" style="height: 400px;">
<div style="height: 300px;">
<el-alert :closable="false"
title="如不需要发布新版本,可无需做任何操作,以正常步骤打包发布即可"
type="info">
</el-alert>
<el-divider content-position="left"></el-divider>
<el-steps direction="vertical" :active="1" space="100px">
<el-step title="版本配置"
description="使用前需要先配置版本信息,并点击保存配置."></el-step>
<el-step title="构建版本"
description="开始构建版本,构建完成后会在构建目录中生成remote文件夹以及update-dev.json更新描述文件"></el-step>
<el-step title="上传更新包"
description="构建完成时,如需发布新版本,则需要点击[上传更新包],更新包会向游戏代码中注入热更逻辑."></el-step>
</el-steps>
</div>
</el-tab-pane>
</el-tabs>
<el-row>
<el-col :span="8">
<el-button type="success" @click="onSave">保存配置信息</el-button>
</el-col>
<el-col :span="8">
<el-button type="danger" @click="onUpload">上传更新包</el-button>
</el-col>
<el-col :span="8">
<el-button type="warning" @click="onStopUpload">终止上传</el-button>
</el-col>
</el-row>
</div>
</body>
<!-- import Vue before Element -->
<script src="../js/vue.2.5.16.js"></script>
<!-- import JavaScript -->
<script src="./element-ui/index.js"></script>
<script>
const fs = require('fs');
const path = require('path');
new Vue({
el: '#app',
data() {
return {
tabName: "versionConfig",
projectPath: "",
versionCfg: {
versionCode: 1,
versionName: "1.0.0",
versionType: "dev",
versionLog: "",
baseUrl: ""
},
ftpCfg: {
host: "127.0.0.1",
port: 21,
user: "",
password: "",
rootPath: "",
keepalive: 100000,
onlyJson: false,
maxThread: 5
},
tip: {
versionCode: "递增版本号,如果与旧版本号相同,则会替换线上版本包.",
versionName: "版本号名称,示例:1.0.0, 用于游戏内显示",
versionType: "版本类型,用于标记当前版本所处的线上环境类型,<br/>如灰度包,内测包,发布包等,不同类型的版本物理隔离,不会相互影响",
versionLog: "版本发布日志,用于游戏内显示更新内容.",
baseUrl: "FTP上传服务器对应的CDN访问URL,仅需要填写根域名即可.",
ip: "FTP上传IP地址,示例:127.0.0.1",
port: "FTP端口号,默认21",
user: "FTP登录验证帐号及密码",
rootPath: "FTP文件上传根目录"
}
};
},
created: function () {
let data = fs.readFileSync(
Editor.url('packages://update-manager/.settings.conf'), 'utf-8');
if (data) {
Object.assign(this, JSON.parse(data));
}
this.projectPath = Editor.url('packages://update-manager');
this.projectPath = this.projectPath.substring(0, this.projectPath.length - 'packages/update-manager'.length)
Editor.log('当前项目路径:', this.projectPath);
},
methods: {
onSave() {
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 += "/";
}
const data = Object.assign({}, {versionCfg: this.versionCfg, ftpCfg: this.ftpCfg});
fs && fs.writeFileSync && fs.writeFileSync(
Editor.url('packages://update-manager/.settings.conf'), JSON.stringify(data, null, 2), 'utf-8');
this.$message({message: "配置保存成功!", type: "success"});
},
onUpload() {
Editor.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) {
Editor.warn('当前仅上传JSON文件,请手动上传remote目录');
return;
}
// 上传更新描述文件.
const updateJsonPath = path.join(this.projectPath, `build/jsb-link/remote/${filePath}`);
Editor.Ipc.sendToMain('update-manager:upload', updateJsonPath, uploadDstPath, this.ftpCfg);
// 上传远程更新包.
let uploadZipPath = path.join(this.projectPath, `build/jsb-link/remote`);
let uploadZipDstPath = `${this.ftpCfg.rootPath}${this.versionCfg.versionType}/${this.versionCfg.versionCode}/remote`;
Editor.Ipc.sendToMain('update-manager:upload', uploadZipPath, uploadZipDstPath, this.ftpCfg);
},
onStopUpload() {
Editor.Ipc.sendToMain('update-manager:uploadStop');
},
notifyMainJs(updateUrl, serverUrl) {
this.$message.info("notifyMainJs");
const filePath = path.join(this.projectPath, 'build/jsb-link/main.js');
const exists = fs.existsSync(filePath);
if (!exists) {
this.$message.error('main.js 不存在,请重新构建');
return false;
}
let mainjs = fs.readFileSync(filePath, 'utf-8');
let varJs = `window.updateUrl="${updateUrl}";\r\n`;
let remoteJs = `window.remoteUrl="${serverUrl}";\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;
fs && fs.writeFileSync && fs.writeFileSync(filePath, mainjs, 'utf-8');
}
this.$message.success("Main.js 热更代码注入成功");
return true;
}
}
})
</script>
</html>