优化Laya ide打包流程:只发布js文件

549 阅读3分钟

前言

由于Laya1.x的版本没有开源发布项目的源文件,也有可能本人的能力问题,没有找到此文件,因此本文主要针对的是Laya1.x版本,至于Laya2.x的版本,可以根据需要去修改.Laya目录下的publish.js来优化打包流程。

痛点

在游戏项目上线期间,会经常打包,每次打包都很费时间,特别对于配置不好的设备,情况更甚,对于我这种懒人来说,可谓难受至极,优化势在必行。

分析

打包过程中所处理的事情如下:

  • 图片资源的压缩 (很耗时间)
  • js文件的压缩混淆 (混淆程度低,代码阅读难度低)
  • 拷贝前面两步的文件到到发布目录

很多时候,我们只是改了代码,并没有改动到UI、场景和图片资源,这时候,我们其实只要替换JS文件就够了,图片资源等资源可以不用重新发布,这样就可以节省90%以上的时间。

做法:场景、UI和图片资源如果发生了变化,先用Laya IDE发布一下项目,后续如果只是JS文件发生改变,其他文件没法有发生改变,就不用Laya IDE再发布项目,只需将bin目录下js文件压缩混淆后,替换掉之前发布目录下的js文件

目标

最终的目标是得到一个zip的压缩包,此压缩包需包含以下几点:

  • 压缩包命名为:游戏名_日期_版本号
  • 压缩包里面的JS文件是包含最新功能的文件,并且已经压缩混淆过(这里使用javascript-obfuscator压缩混淆)

过程

此优化功能被添加到基于node.js的yargs库写的脚手架工具上,目的是为了能更方便使用命令行命令。具体的yargs功能,这里就不多阐述了,有兴趣的朋友可以去研究。

这里使用到async.js的series方法,按顺序处理任务,并且会等上一个任务完成后,才会执行下一个任务

const exec = require('child_process').exec;
const date = require("silly-datetime");
const archiver = require('archiver');
const async = require("async");
const path = require("path");
const fs = require("fs");

module.exports = {
  // 这里 这里假设yargs的主命令是minigame, 这个文件对应的命令行指令就是 minigame pack
  command: 'pack',
  desc: '',
  builder: (curYargs) => {

  },
  handler: (argv) => {
    const gameName = "xxx";
    // 待加密的js文件的根路径
    const willEncryptJS = "bin目录下的js文件的根路径";
    const output = "游戏包发布的路径";
    const today = date.format(new Date(), "YYYY-MM-DD");
    // 第二个参数用来输入版本号, 完整的命令: minigame pack ${version}
    const version = process.argv[3];
    const gamePathName = `${gameName}_${today}_v${version}`;
    const gameOutput = path.join(output, `${gamePathName}`);
    async.series({
      // 第一步:创建 游戏名称_日期_版本号的目录 gameOutput
      one:function(done){        
        fs.mkdir(gameOutput, { recursive:true }, (err) => {
          if (err) {
            return console.error("====> error:", err);            
          }
          console.log("one done");
          done(null, "one");
        });
      },
      // 第二步:将laya发布后的web里面的内容考到 gameOutput
      two:function(done){
        const source = path.join(output, "web");
        fs.cp(source, gameOutput, { recursive: true }, (err) => {
          if (err) {
            console.error(err);
          } else {
            console.log("two done");
            done(null, "two");
          }          
        });
      },
      // 第三步:删除gameOutput/js/src文件夹
      three:function(done){
        const srcPath = path.resolve(gameOutput, "js/src");
        fs.rm(srcPath, { recursive: true}, (err) => {
          if (err) {
            console.error(`remove src dir error: ${err}`)
          } else {
            console.log("three done");
            done(null, "three");
          }
        });
      },
      // 第四步:加密bin/js/src的所有js文件,并且输出到gameOutput/js/src下
      four:function(done){
        const dst = path.resolve(gameOutput, "js/");
        const cmdStr = `javascript-obfuscator ${willEncryptJS} --output ${dst}`;
        exec(cmdStr, function (err, stdout, srderr) {
          if (err) {
            console.error("javascript-obfuscator error: ", srderr);
          } else {
            console.log("four done");
            done(null, "four");
          }
        });
      },
      // 第五步:将gameOutput输出zip压缩包
      five:function(done){
        // 创建可写流来写入数据
        const output = fs.createWriteStream(gameOutput + ".zip");// 将压缩包保存到当前项目的目录下
        const archive = archiver('zip', {zlib: {level: 9}});// 设置压缩等级

        // on
        output.on('close', function() {
          console.log("five done");
          done(null, "five");
        });
        archive.on('error', function(err) {
          console.error("five error: ", err);
        });

        // 建立管道连接
        archive.pipe(output);
        archive.directory(gameOutput, false);

        // 完成压缩
        archive.finalize();

      }
    },function(error, result){
      console.log("result done");
        if (error) {
          console.error("====> result error: ", error);
        } else {
          console.log("====> result:", result);
        }
    })

  }
}

完成上述代码,只要打开终端,输入minigame pack 1,就会输入最终的游戏zip包,假设游戏的名字就coc, 今天是2022年11月4日,输入上述指令后,最后会成coc_2022-11-04_v1.zip包

因此打包的时候,如果只是JS文件改变,这是只要输入minigame pack ${version},几秒钟就会生成最终压缩包,可以直接上线,工作效率非常感人