参考
layacmd
资源版本管理
一、layacmd
注意,官方在2017.12.13发帖子(更改layacmd名字为layaair-cmd)说,由于npm账号问题导致无法修改之前的layacmd文件,所以现将layacmd名字改为layaair-cmd。
修改之后的文档在官网的地址
在npmjs的地址
相关的帮助文档也变成了layaair-cmd,当然安装方式也由之前的npm install layacmd -g
,变成npm install layaair-cmd -g
layaair-cmd的大部分子命令都需要当前工作目录下包含layaair项目,少数命令可以手动指定输入目录,如guetzl,atlas命令则是即可以直接$ layaair-cmd atlas,也可以指定输入目录。
1.编译
layacmd compile
2.发布
layacmd publish -n 1.0.1
3.导出UI
layacmd ui -c -a
4.资源版本控制
layacmd resourceVersion -i res -o . -n 1.0.0
5.guetzli
layacmd guetzli -i src
该命令不需要当前目录包含layaair项目,取而代之的是,你需要指定输入目录。压缩成功后,源文件会被修改。压缩失败则源文件保持不变。
guetzli的压缩过程很慢,而且占用资源大,所以可能要等待些时间。最好在资源版本控制生成的文件夹中使用guetzli压缩,这可以保证不会重复压缩一张图。
注意这里只有-i,没有-o,也就是直接改了源文件,不如用Gulp脚本来运行guetzli更方便
6.本地服务器
layacmd open 9000 -s
9000是端口号,-s 表示 don't open browser
这个很明显,用的是anywhere
二、资源版本管理
资源版本控制用于为资源生成版本。版本号默认从数字1000开始递增,如果传入--versionName参数,则使用用户指定的版本名称。下次建立建立版本时如果没有再次指定--name,版本号为1002,因为每次生成版本,资源版本控制内部版本计数器都会递增。
在建立版本时,相对于上次版本建立,修改了的文件或者新增的文件会被记录在新版本中。如果没有新增文件或者没有修改文件,不会有新版本生成。
在最终使用资源时,不允许使用上层相对路径,即路径中包含“..”。
$ layacmd resourceVersion -h
Usage: layacmd-resourceVersion [options]
Options:
-h, --help output usage information
-V, --version output the version number
-i --input 资源目录
-o --output
该命令不需要当前目录包含layaair项目,取而代之的是,你需要指定输入目录。
比如:
layacmd resourceVersion -i res -o . -n 1.0.0
这里-i代表资源路径,-o . 代表版本资源输出路径为当前路径,当然开发者也可以自定义输出路径,比如定义路径为version文件夹等等,-n 1.0.0初始化版本为1.0.0。
参考资源版本管理问题官方回复:
Q:这个 -i res 的意思是只处理res目录吗?如果res目录之外还有目录跟js文件需要打版本那要怎么搞呢?
A:一般一个项目只会针对一个资源文件夹,很少出现2个完全分离的资源文件夹,所以我们的命令行目前也只能针对一个资源文件夹做资源版本控制,-i res ,,,res可以为任意路径!
1.资源版本
名为1000、1001、1002的文件夹是默认资源版本名称,里面保存的是对应版本被修改了的资源。
2.record记录文件
.record在Unix-like系统中是隐藏文件。这个文件保存最近的版本建立信息,资源版本控制由此来判定建立新版本时哪些文件被修改。这个文件不能被删除,如果这个文件丢失,之前建立的版本就会丢失,相当于重新开始建立版本。
3.manifest.json
{
"res1": "1000",
"res2": "1000",
"res3": "1002",
"sub\\res3": "1000",
"sub\\res4": "1000"
}
从中得到每个资源的最新版本号,从这些文件夹读取manifest.json对应的版本资源(资源根目录/版本号/相对文件路径)
4.资源版本切换
由于manifest.json保存各版本的文件版本号。所以只需要保留历史manifest.json即可使用对应版本的资源。
三、实践
package
{
import laya.net.Loader;
import laya.net.ResourceVersion;
import laya.utils.Handler;
public class Main
{
private var configUrl:String ="manifest.json?"+Math.random();;
public function Main()
{
Laya.init(500,500);
ResourceVersion.enable(configUrl,Handler.create(this,this.completeHandler));
}
private function completeHandler(e:Object):void
{
var obj:Object = Laya.loader.getRes(configUrl);
var data:Array =[
{"url":"res/sound/a.mp3","type":Loader.BUFFER},
{"url":"res/data/data.data","type":Loader.TEXT}
]
Laya.loader.load(data,Handler.create(this,resComplete));
}
private function resComplete():void
{
}
}
}
按照资源版本管理,如果我们修改了文件,但一直用
layacmd resourceVersion -i res -o . -n 1.0.0
来打包,其实mainfest.json是不会变的。当然新增文件,会添加新的一行,版本号还是1.0.0
0 new files (+)
0 deletions (-)
1 modifications(*)
5 no changes (=)
从上面的log中也能看出,这个工具实际上在对比文件变化,记录到mainfest.jon中,标清每一个文件要去1.0.0里取,还是1.0.1里取。
四、问题:
1.图集和未打包图片不在一个路径下
IDE的资源中,有一部分是不打包的,按照默认设置,不打包的图片直接导到bin目录下,而打包的图集资源是在res/atlas下面。这样上面讲的资源版本管理,如果只针对res目录,那么不打包的资源就不在控制范围内了。
解决办法就是把未打包图片,也放到res下面。
这样会出现运行过程中加载不到这些外部图片,因为basePath默认指向根目录。解决办法就是改basePath。具体参考Laya Loader 图集 图片
var addPath:string = Laya.URL.basePath += "res/";
Laya.URL.rootPath=Laya.URL.basePath = addPath;
2.在哪里做资源版本?
Q:资源管理,是放在bin下,在发布release时一并导出。还是发完release后,再去release下的资源目录中做资源管理呢?
A:LAYA IDE自带的发布功能,每次都需要一个新的版本号,比如1.0.4。那么在1.0.4资源目录中,是没办法找到之前的mainfest和资源的,除非去1.0.3里,复制过来。然后再运行layacmd。另外,还要添加代码
var configUrl:string ="manifest.json?"+Math.random();
Laya.ResourceVersion.enable(configUrl,Handler.create(this,this.completeHandler));
虽然可以在debug版本中通过标记变量判断是release版本才执行这段代码。
综上,我选择了在debug中就做资源版本
3.直接在res目录下运行layacmd resourceVersion -i . -o . -n 1.0.0
,生成的mainfest.json中都是这样的:"res\/1.0.0\/res\/atlas\/comp.json": "1.0.1",
.然后ResourceVersion.as中这段代码就会出问题
/**
* 为加载路径添加版本前缀。
* @param originURL 源路径。
* @return 格式化后的新路径。
*/
public static function addVersionPrefix(originURL:String):String {
if (manifest && manifest[originURL])
return manifest[originURL] + "/" + originURL;
return originURL;
}
因为传进来的参数originURL前面并没有带res,所以if (manifest && manifest[originURL])
判断 失效。于是我悲剧地重写这个方法:
Laya.ResourceVersion.addVersionPrefix=function(originURL){
originURL = "res/"+originURL;
if (Laya.ResourceVersion.manifest && Laya.ResourceVersion.manifest[originURL])
return Laya.ResourceVersion.manifest[originURL]+"/"+originURL;
return originURL;
}
ok,一切正常了。然而事情并没完,当我修改文件,去打1.0.1时,由于还是在res内打包,就出现把之前的1.0.0也打包到1.0.1里……
所以我们不能在res目录内用命令来分资源版本。
4.重新回到bin目录下,使用命令:
layacmd resourceVersion -i res -o . -n 1.0.0
manifes.json:
"res\/atlas\/.rec": "1.0.0"
发现1.0.0下面已经有res目录,所以basePath不需要再添加res了。
那么addVersionPrefix还要不要重写呢,测试了下,还是需要的。因为IDE中未打包资源的skin并未携带res前缀,虽然其它资源我们可以手动上res前缀,比如
function loadSound():void
{
var obj:Object = Laya.loader.getRes("res/sound/a.mp3");
}
function resComplete():void
{
Laya.loader.load([{ url: "res/atlas/comp.json",
type: Loader.ATLAS }], Handler.create(this, this.onLoaded));
}
重写addVersionPrefix方法就相当于给所有经过版本控制的资源,都添加了res前缀,这样不管是图集,音乐,还是外部加载图片,都不需要再添加res前缀了
5.最后根据debug,release来分策略加载
private loadByResVersion() {
var bgInfo = window["bgInfo"];
if (!bgInfo["debug"]) {
//重写版本控制中路径方法
Laya.ResourceVersion.addVersionPrefix = function (originURL) {
originURL = "res/" + originURL;
if (Laya.ResourceVersion.manifest && Laya.ResourceVersion.manifest[originURL]) {
return Laya.ResourceVersion.manifest[originURL] + "/" + originURL;
}
return originURL;
}
var configUrl: string = "manifest.json?" + Math.random();
Laya.ResourceVersion.enable(configUrl, Laya.Handler.create(this, this.beginGameLoad));
} else {
var addPath: string = Laya.URL.basePath += "res/";
Laya.URL.rootPath = Laya.URL.basePath = addPath;
this.beginGameLoad();
}
}