当前位置: 首页 > news >正文

网站推广优化技巧app开发软件外包

网站推广优化技巧,app开发软件外包,北京网站优化外包,福田专业网站建设公司哪家好热更新指的是#xff1a;electron 程序已经开启#xff0c;在不关闭的情况下执行更新#xff0c;需要我们把远程的app.asar文件下载到本地执行替换#xff0c;然而 在electron应用程序开启状态是无法直接下载app.asar文件的#xff0c;下载会检查出app.asar文件被占用electron 程序已经开启在不关闭的情况下执行更新需要我们把远程的app.asar文件下载到本地执行替换然而 在electron应用程序开启状态是无法直接下载app.asar文件的下载会检查出app.asar文件被占用所以我们需要在本地将app.asar文件反编译编译出一个app文件夹里面有项目所需的所有源码文件这时通过vue或react打包的渲染进程代码是经过压缩的但是主进程代码会直接暴露所以刚好我们可以将主进程代码做压缩混淆然后生成一个app.zip压缩包,上传至服务器然后下载这个压缩包解压将其编译成app.asar文件替换到resources目录中从而实现electron软件的热更新。 主进程nodejs侧代码 const {app, BrowserWindow, ipcMain} require(electron) const path require(path) const fs require(fs); const http require(http); const asar require(asar); const AdmZip require(adm-zip); const fsExtra require(fs-extra);const mainData require(./mainData); const txtConsole require(./txtConsole);//当前环境 const production mainData?.production;//Electron 安装根目录 const rootPath production dev ? path.resolve(./public) : path.dirname(app.getPath(exe)); mainData.rootPath rootPath;// 软件更新配置信息目前需要手动修改~~~ const winUpdateConfig {currentVersion: null, //当前版本updateVersionFilePath: http://103.117.121.53:8002/latest, //远程版本信息路径updateFilePath: http://103.117.121.53:8002/app.zip, //远程包路径localUpdateVersionFilePath: production dev ? ${rootPath}/latest : ${rootPath}/resources/latest, //本地版本信息路径localUpdateFilePath: production dev ? rootPath : ${rootPath}/resources, //本地包路径updateSteps: [{id: 1, desc: 开始下载并解压更新文件,请勿重启, active: active},{id: 2, desc: 下载并解压完成, 开始覆盖安装, active: wait},{id: 3, desc: 更新完毕, 即将重启请稍候(第3步完成后也可以手动重启), active: wait},], //更新步骤 active:正在进行 wait:等待 success:执行成功 error: 执行失败 };let versionInfo ; //获取最新版本信息 let locallatest ; //本地版本号function appInit() {txtConsole.log(初始化);try {locallatest fs.readFileSync(winUpdateConfig.localUpdateVersionFilePath, utf-8);locallatest JSON.parse(locallatest);//设置当前版本信息winUpdateConfig.currentVersion locallatest?.version;txtConsole.log(已设置当前版本信息, locallatest?.version);//删除日志txtConsole.clearLog();} catch (err) {txtConsole.log(err);} }//创建主窗口 function createWindow() {const mainWindow new BrowserWindow({width: 800,height: 600,webPreferences: {// preload: path.join(__dirname, preload.js),nodeIntegration: true,contextIsolation: false,webSecurity: false, //禁用同源策略}});mainWindow.loadFile(index.html).then();// 打开开发者工具 控制台if (mainData.winControl dev) {mainWindow.webContents.openDevTools();}// 检查更新ipcMain.on(window-version, function (event) {try {txtConsole.log(检查更新, versionInfo);if (!versionInfo) {!event?.sender?.isDestroyed() event?.sender?.send(window-version-err-msg, 更新文件读取失败);return;}const v {...(versionInfo || {})};//最新版本号let firNewVersion versionInfo?.version?.split(.)?.[0]; //第一位let secNewVersion versionInfo?.version?.split(.)?.[1]; //第二位let thiNewVersion versionInfo?.version?.split(.)?.[2]; //第三位//当前版本号let firOldVersion versionInfo?.currentVersion?.split(.)?.[0]; //第一位let secOldVersion versionInfo?.currentVersion?.split(.)?.[1]; //第二位let thiOldVersion versionInfo?.currentVersion?.split(.)?.[2]; //第三位//按位比较是否需要更新if (Number(firNewVersion || 10000) Number(firOldVersion || 10000)) {v[versionVisible] true;}else if (Number(secNewVersion || 10000) Number(secOldVersion || 10000)) {v[versionVisible] true;}else if (Number(thiNewVersion || 10000) Number(thiOldVersion || 10000)) {v[versionVisible] true;}else {v[versionVisible] false;v[currentVersion] versionInfo?.version;}if (!v[versionVisible]) {let latest fs.readFileSync(winUpdateConfig.localUpdateVersionFilePath, utf-8);latest JSON.parse(latest);latest.version versionInfo?.version || latest?.version;latest.currentVersion versionInfo?.version || latest?.version;fs.writeFileSync(winUpdateConfig.localUpdateVersionFilePath, JSON.stringify(latest));txtConsole.log(hot: , latest.version);}txtConsole.log(versionVisible , v[versionVisible]);!event?.sender?.isDestroyed() event?.sender?.send(window-version-msg, v);} catch (err) {!event?.sender?.isDestroyed() event?.sender?.send(window-version-err-msg, 更新文件读取失败);txtConsole.log(检查更新err, err);}});// 下载更新文件ipcMain.on(window-download-newfile, function (event) {txtConsole.log(开始下载并解压更新文件 热更新);event?.sender?.send(window-download-newfile-msg, winUpdateConfig.updateSteps);const file fs.createWriteStream(path.resolve(winUpdateConfig.localUpdateFilePath, app.zip),);let downloadedBytes 0;let totalBytes 0;http.get(winUpdateConfig.updateFilePath, (response) {totalBytes parseInt(response?.headers[content-length], 10);let prevTimestamp Date.now();response?.on(data, (chunk) {downloadedBytes chunk.length;const timestamp Date.now();const timeDiff timestamp - prevTimestamp;// 每1.5秒钟更新一次进度if (timeDiff 1500) {const progress ((downloadedBytes / totalBytes) * 100).toFixed(2);txtConsole.log(下载进度${progress}% , totalBytes);prevTimestamp timestamp;event?.sender?.send(window-download-progress-msg, Math.min(Number(progress), 80));}});response?.pipe(file);}).on(error, (err) {txtConsole.log(下载错误: ${err.message});event?.sender?.send(window-download-newfile-err-msg, 更新文件下载失败);});file?.on(finish, function () {event.sender.send(window-download-progress-msg, 90);winUpdateConfig.updateSteps[0][active] success;winUpdateConfig.updateSteps[1][active] active;event?.sender?.send(window-download-newfile-msg, winUpdateConfig.updateSteps);// 文件已经完全写入磁盘开始解压try {const zip new AdmZip(path.resolve(winUpdateConfig.localUpdateFilePath, app.zip), void 0);zip.extractAllTo(winUpdateConfig.localUpdateFilePath, true, void 0, void 0);} catch (err) {txtConsole.log(解压异常 error: , err);!event?.sender?.isDestroyed() event?.sender?.send(window-download-newfile-err-msg, 解压异常);return;}winUpdateConfig.updateSteps[1][active] success;winUpdateConfig.updateSteps[2][active] active;event?.sender?.send(window-download-newfile-msg, winUpdateConfig.updateSteps);event?.sender?.send(window-download-progress-msg, 95);const sourceDir path.join(winUpdateConfig.localUpdateFilePath, apps);const destPath path.join(winUpdateConfig.localUpdateFilePath, app.asar);asar.createPackage(sourceDir, destPath).then(() {if (fs.existsSync(path.resolve(winUpdateConfig.localUpdateFilePath, app.zip))) {fs.unlinkSync(path.resolve(winUpdateConfig.localUpdateFilePath, app.zip));}txtConsole.log(更新完毕);event.sender.send(window-download-progress-msg, 100);winUpdateConfig.updateSteps[2][active] success;event?.sender?.send(window-download-newfile-msg,winUpdateConfig.updateSteps,success,);//设置当前版本信息try {let latest fs.readFileSync(winUpdateConfig.localUpdateVersionFilePath, utf-8);latest JSON.parse(latest);latest.version versionInfo.version;fs.writeFileSync(winUpdateConfig.localUpdateVersionFilePath, JSON.stringify(latest));txtConsole.log(更新后已设置当前版本信息, latest?.version);//删除apps文件夹 防止执行文件夹内的代码deleteFolderRecursive(sourceDir);} catch (err) {txtConsole.log(err);}}).catch((err) {txtConsole.log(创建asar文件失败: , err);event.sender.send(window-download-newfile-err-msg, asar文件创建失败);});});file?.on(error, function (err) {txtConsole.log(更新asarError: , err);event.sender.send(window-download-newfile-err-msg, err);});}); }//检查更新 function checkUpdate(callback) {txtConsole.log(检查更新);http.get(winUpdateConfig.updateVersionFilePath, (res) {res.on(data, (chunk) {versionInfo chunk;});res.on(end, () {try {if (versionInfo versionInfo?.indexOf(404 Not Found) 0) {versionInfo JSON.parse(versionInfo);winUpdateConfig.updateFilePath versionInfo.updateFilePath;//热更最新信息let asarVersionInfo {newVersionDesc: versionInfo.newVersionDesc,currentVersion: winUpdateConfig.currentVersion,};versionInfo.currentVersion winUpdateConfig.currentVersion;let writeNewVersonInfo;//不存在则创建latest文件if (!fs.existsSync(winUpdateConfig.localUpdateVersionFilePath)) {writeNewVersonInfo versionInfo;txtConsole.log(latest文件重新创建成功);}else {let currentVersion fs.readFileSync(winUpdateConfig.localUpdateVersionFilePath,utf8,);currentVersion JSON.parse(currentVersion);currentVersion[updateFilePath] ;//只覆盖热更版本信息writeNewVersonInfo {...currentVersion, ...asarVersionInfo};}//将整理好的配置文件信息写入fs.writeFileSync(winUpdateConfig.localUpdateVersionFilePath,JSON.stringify(writeNewVersonInfo),);// txtConsole.log(已将新的更新配置文件信息写入, JSON.stringify(writeNewVersonInfo));txtConsole.log(更新检查完毕最新版本${versionInfo.version}, 当前版本${asarVersionInfo.currentVersion},);txtConsole.log(-------------------------------------------------------);callback?.(null, versionInfo);}else {txtConsole.log(更新配置文件读取失败);callback?.(更新配置文件读取失败);}} catch (err) {txtConsole.log(更新配置文件覆写失败);callback?.(更新配置文件覆写失败);}});}).on(error, (error) {txtConsole.log(更新配置文件下载失败: ${error.message});callback?.(更新配置文件下载失败);}); }//删除更新文件 function deleteFolderRecursive(folderPath) {if (fs.existsSync(folderPath)) {fs.readdirSync(folderPath).forEach((file) {const curPath path.join(folderPath, file);if (fs.lstatSync(curPath).isDirectory()) {// 递归删除子文件夹deleteFolderRecursive(curPath);}else {// 删除文件fs.unlinkSync(curPath);}});// 删除子文件夹后删除文件夹本身fs.rmdirSync(folderPath);} }app.whenReady().then(() {//初始化appInit();//检查更新checkUpdate(async (check, versionInfo {}) {if (check) {txtConsole.log(检查更新执行失败);}else {txtConsole.log(检查更新执行成功);}createWindow();app.on(activate, function () {if (BrowserWindow.getAllWindows().length 0) createWindow()})}); })app.on(window-all-closed, function () {if (process.platform ! darwin) app.quit() }) 渲染进程侧代码以原生为例: !DOCTYPE html html headmeta charsetutf-8/meta http-equivX-UA-Compatible contentIEedge/meta nameviewport contentwidthdevice-width,initial-scale1.0/titleHello World!/title /head body h1Hello World!/h1 button onclickonCheckUpdate()检查更新/button button onclickonUpdateVersion()测试更新/buttondiv classupdateInfo/div div classdescInfo/divscriptconst {ipcRenderer} require(electron);const onVersion {updateDsec: [],process: 0,};//检查更新function onCheckUpdate() {ipcRenderer?.send(window-version);ipcRenderer?.once(window-version-msg, (_, bool) {document.querySelector(.updateInfo).innerHTML JSON.stringify(bool);});ipcRenderer?.once(window-version-err-msg, (_, err) {document.querySelector(.updateInfo).innerHTML err;});}//测试更新function onUpdateVersion() {onVersion.updateDsec [];ipcRenderer?.send(window-download-newfile);//监听下载版本信息ipcRenderer?.on(window-download-newfile-msg, (event, updateDsec, status) {if (!event.handel) {event.handel true;onVersion.isStartUpdate true;onVersion.updateDsec updateDsec;document.querySelector(.descInfo).innerHTML updateDsec.map(item span stylecolor:${item.active success ? green : orangered}${item.desc}/span).join(/br);if (status success) {ipcRenderer?.send(window-restart-app);}onVersion.visible true;}});//监听更新包下载进度ipcRenderer?.on(window-download-progress-msg, (event, process) {if (!event.handel) {event.handel true;document.querySelector(.updateInfo).innerHTML String(完成进度 process %);}});//监听下载版本错误信息ipcRenderer?.once(window-download-newfile-err-msg, (event, res) {console.log(res)});} /script /body /html 轮子实现压缩混淆反编译 //生成 反编译app.asar 并生成压缩包 const asar require(asar); const path require(path); const fs require(fs); const fsExtra require(fs-extra); const zlib require(zlib); const archiver require(archiver); const uglify require(uglify-js); const moment require(moment); const {exec} require(child_process); const JavaScriptObfuscator require(javascript-obfuscator);const mainData require(./mainData);const startTime moment().unix(); //秒级时间戳const rootPath path.resolve(__dirname); // 获取项目根路径 const asarPath ./build/win-ia32-unpacked/resources/app.asar; // 获取 app.asar 文件路径 const sourceDir ./apps; // 要压缩的文件夹路径 const asarAppPath ./apps/apps; // asar反编译文件的存放路径 const buildPath ./build; //electron 打包后的build文件夹 const destFile ./app.zip; // 压缩后的文件路径 const publicLogPath ./public/log.txt; const publicAsarPath ./public/app.asar;// 配置环境路径为项目根路径 const env Object.assign({}, process.env, {PATH: rootPath ; process.env.PATH,npm_config_prefix: C:\\Program Files\\nodejs\\npm, // 这里是你的 npm 安装路径 });const Console {log(p1 , p2 , p3 , p4 , p5 ) {console.log(${moment().format(HH:mm:ss)} | ${p1}${p2}${p3}${p4}${p5});}, };//压缩主进程 main.js 相关代码 function zipMainJS() {try {const dir path.resolve(asarAppPath, main.js);const dirJs fs.readFileSync(dir, utf8);//压缩代码 mangle: true,const result uglify.minify(dirJs, {mangle: {toplevel: true,},});// 混淆代码const obfuscationResult JavaScriptObfuscator.obfuscate(result.code, {compact: true,controlFlowFlattening: true,controlFlowFlatteningThreshold: 0.75,numbersToExpressions: true,simplify: true,shuffleStringArray: true,splitStrings: true,stringArrayThreshold: 0.75,});fs.writeFileSync(dir, obfuscationResult.getObfuscatedCode());return true;} catch (err) {Console.log(err);return false;} }//添加开始执行 app.asar反编译逻辑 async function init() {//执行app.asar 反编译、压缩、混淆Console.log(正在执行app.asar 反编译、压缩、混淆);// 将 app.asar 解压缩到指定文件夹中asar.extractAll(asarPath, asarAppPath);Console.log(正在压缩app文件夹到项目根目录);//压缩main.js相关代码let zipRes zipMainJS();if (!zipRes) {Console.log(!!!压缩main.js主进程代码失败);return;}Console.log(主进程相关代码压缩完毕);//再次生成 app.asarasar.createPackage(asarAppPath, asarPath).then(() {Console.log(已再次生成 app.asar 文件代码压缩后的asar文件);onAppZip();}); }function onAppZip() {// 创建一个可写流将压缩后的文件写入到目标文件中const destStream fs.createWriteStream(destFile);// 创建一个 archiver 实例const archive archiver(zip, {zlib: {level: zlib.constants.Z_BEST_COMPRESSION},});// 将可写流传递给 archiver 实例archive.pipe(destStream);// 将要压缩的文件夹添加到 archiver 实例中archive.directory(sourceDir, false, null);// 完成压缩并关闭可写流archive.finalize();// 监听可写流的 close 事件表示压缩完成destStream.on(close, () {Console.log(压缩完毕压缩包路径【${path.resolve(__dirname, destFile)}】);Console.log(共用时 (moment().unix() - startTime) 秒);}); }try {if (mainData?.production dev) {throw 请将环境切换为生产环境 mainData.js 【const production pro;】;}if (mainData?.winControl dev) {throw 请关闭主窗口调试控制台 winControl;}fsExtra.removeSync(buildPath);Console.log(已删除build文件夹内容);fsExtra.removeSync(publicLogPath);Console.log(已删除public/log.txt);fsExtra.removeSync(publicAsarPath);Console.log(已删除public/app.asar);fsExtra.removeSync(asarAppPath);Console.log(已删除apps);//执行 打包命令Console.log(正在执行【npm run packager32】命令);exec(npm run packager32, env, (error, stdout, stderr) {if (error) {Console.log(执行出错: ${error});return;}stderr Console.log(【npm run packager32】 stderr, stderr);//生成app.init();});} catch (err) {Console.log(err); }示例Demo: https://github.com/qglovehy/electron-updater.git
http://www.zqtcl.cn/news/357037/

相关文章:

  • 聚成网站建设艺术公司网站定制中心
  • 阿里云上可以做网站吗十六局集团门户网
  • 门户网站建设询价函有哪些网站可以做设计挣钱
  • 如何建立自己网站奔奔网站建设
  • 自由做图网站做网站所用的工具
  • 广西南宁做网站专业网站建设案例
  • 视屏网站的审核是怎么做的群辉 搭建wordpress
  • 嘉兴网站快速排名优化衡阳网站建设制作
  • 建设公共资源交易中心网站成都APP,微网站开发
  • dede网站地图修改厦门百度seo
  • 可以做行程的网站网站详情怎么做的
  • 网站建设心得8000字营销型网站建设的注意事项
  • 织梦购物网站整站源码哈尔滨网站建设技术托管
  • 做推广的网站微信号企业免费网站制作
  • 做旅游网站的引言上海公司网站建设哪家好
  • 找项目去哪个网站网站建设一条龙全包
  • 网站 数据库 模板网站系统建设合作合同范本
  • 网站空间租赁费用企业网站建设需要多少钱知乎
  • 免费建网站哪个模板多浅谈学校网站建设
  • 精致的个人网站手机网站建设基本流程图
  • 优秀网站网页设计图片主机屋做网站视频
  • 安徽网站建设电话编程一个最简单游戏代码
  • 西宁圆井模板我自己做的网站在线平面设计图
  • 浦口区网站建设技术指导做软件需要网站吗
  • 丹东有做公司网站的吗搜索引擎 wordpress
  • 做网站代理国内课程网站建设现状
  • 中国建设银行手机网站下载从零开始建设企业网站
  • 网站友情链接怎么弄seo平台
  • 建设网站一定要备案吗嘉兴做网站设计
  • 如何制作营销网站模板做外贸需要关注的网站有什么好处