-前言-

不知道你知不知道Laya有一个查找未被使用的资源功能,在UI编辑器状态下按F4弹出,不过这个功能实在鸡肋,只能查找在page中引用过的资源,但是我们正常开发下很多资源是在代码中,或者配置到配置档中的,所以需要根据自己的需求更改。如果放到Unity我估计就放弃了,直接写脚本来跑删除逻辑,不过既然Laya是开源引擎,引擎代码又是基于nodejs环境写的,那通过简单修改就能实现我们想要的结果了。

-正文-

找到对应逻辑代码

首先到你Laya的安装目录下找到resources->app->out->vs->layaEditor->layabuilder.max.js,关于IDE相关的代码就在这里。app目录是自带nodejs环境的,因此我们可以调用诸如fs这些文件操作API。控制查找未被使用资源的面板名称为FindUnUsedRes。我们所要实现的功能主要就着手修改这个类。

//当我们点击查找按钮之后的逻辑处理
__proto.onFindBtnClick=function(e){
	this.resultBox.visible=true;
	this._arr=ResManager.findUnUsed();
	this.msgTxt.text=Sys.lang("共找到 {0} 个资源",this._arr.length);
	this.checkSelectAll.selected=true;
	this.onCheckSelectAllChange(null);
	this.checkSelectAll.on("change",this,this.onCheckSelectAllChange);
}

找到这里就好说了,我们修改find规则就能符合我们想要查找的资源类型。

修改UI界面

作为一个合格的前端肯定要符合我们使用习惯,在不修改现有使用的情况下,我们添加两个复选框,codeCheck及whiteListCheck,这两个复选框选中后我们就去代码中匹配资源以及在我们定义的白名单中匹配资源。LayaIDE用的UI库与我们项目开发中使用的UI库是一样的,熟悉Laya的同学应该会熟悉这套UI框架。

//构造函数
function FindUnUsedRes(){
	this._arr=null;
	this.isCodeChange=false;
	FindUnUsedRes.__super.call(this);
	this.findBtn.on("click",this,this.onFindBtnClick);
	this.list.mouseHandler=new Handler(this,this.onList);
	this.delBtn.on("click",this,this.onDelBtnClick);

	//以下为我们自己添加的代码
	this.codeCheck = new CheckBox("comp/checkbox.png");
	this.codeCheck.pos(this.findBtn.x + this.findBtn.width + 20,
		this.findBtn.y + this.findBtn.height / 2 - this.codeCheck.height / 2);			
	this.addChild(this.codeCheck);
	var tfCodeCheck = new Label("查找代码");
	tfCodeCheck.fontSize = 14;
	tfCodeCheck.color = "#ffffff";
	tfCodeCheck.pos(this.codeCheck.x + this.codeCheck.width + 5,this.codeCheck.y);
	this.addChild(tfCodeCheck);

	this.whiteListCheck = new CheckBox("comp/checkbox.png");
	this.whiteListCheck.pos(this.codeCheck.x,this.codeCheck.y + this.codeCheck.height + 5);
	this.addChild(this.whiteListCheck);

	var tfWhite = new Label("检测白名单");
	tfWhite.fontSize = 14;
	tfWhite.color = "#ffffff";
	tfWhite.pos(this.whiteListCheck.x + this.whiteListCheck.width + 5,this.whiteListCheck.y);
	this.addChild(tfWhite);
}

以上我们添加了两个复选框以及复选框的说明文本,不过目前还没有实现对应筛选逻辑,我们重启或者刷新IDE按F4查看变化如下。

怎么移除项目中的yarn 删除项目_怎么移除项目中的yarn

处理查询逻辑

查询逻辑通过ResManager->findUnUsed接口查询未被使用的资源。之前是没有参数的查询,为了实现我们的功能,我们把两个复选框的状态传入这个接口,当复选框选上的时候就执行我们新写上去的逻辑。

ResManager.findUnUsed=function(isCodeCheck,useWhiteList){
    //以下为新加代码
	(isCodeCheck===void 0) && (isCodeCheck= false);
	(useWhiteList===void 0) && (useWhiteList = false);
    //以上为新加代码

	var reses;
	reses=ResFileManager.getAllResLinkList();
	var pages=FileManager.getFileList(FileManager.getWorkPath("laya/pages/"));
	var i=0,len=0;
	var a;
	for(var $each_a in pages){
		a=pages[$each_a];
		var path=a;
		if(FileTools.isDirectory(path))continue ;
		var txt=FileManager.readTxtFile(path);
		for (i=reses.length-1;i >-1;i--){
			var item=reses[i];
			if(item.indexOf("@")>=0||item.indexOf("$")>=0){
				reses.splice(i,1);
				continue ;
			}
			if (txt.indexOf("\""+item+"\"")!=-1){
				reses.splice(i,1);
			}
		}
	};
    //以下为新加代码
	if(useWhiteList){
        //读取项目根目录下unusewhitelist.json配置
		var white = FileManager.readJSONFile(FileManager.getWorkPath("") + "\\unusewhitelist.json");
		if(white instanceof Array && white.length > 0){
			for(i=reses.length - 1;i > -1;i--){
				var item = reses[i];
				if(item.indexOf("@")>=0||item.indexOf("$")>=0){
					reses.splice(i,1);
					continue ;
				}
				for(var j = 0;j < white.length;++j){
					var wi = white[j];
					if(item.indexOf(wi) != -1){
						reses.splice(i,1);
						break;
					}
				}
			}
		}
	}

	if(isCodeCheck){
        //直接读取bin目录下经过编译打包后的bundle.js文件
		var codes = FileManager.getFileList(FileManager.getWorkPath("bin/js/"));
		for(var jsI in codes){
			var jsPath = codes[jsI];
			if(FileTools.isDirectory(jsPath))continue ;
			var txt = FileManager.readTxtFile(jsPath);
			for(i=reses.length - 1;i > -1;i--){
				var item = reses[i];
				if(item.indexOf("@")>=0||item.indexOf("$")>=0){
					reses.splice(i,1);
					continue ;
				}
				if (txt.indexOf("\""+item+"\"")!=-1){
					reses.splice(i,1);
				}else{
					var gR = item.split(new RegExp("\\d+"));							
					if(txt.indexOf("\""+gR[0]+"\"") != -1){
						reses.splice(i,1);
					}//TODO 增加匹配_
				}
			}
		}
	}
    //以上为新加代码
	var rst;
	rst=[];
	len=reses.length;
	for(i=0;i<len;i++){
		rst.push({label:reses[i],path:FileManager.getResPath(reses[i])});
	}
	return rst;
}

上面代码中注释之间的就是我们新加上的处理代码,逻辑其实很简单,就是字符串匹配。如果你有别的匹配需求还有可以写别的,我这里只是抛砖引玉,代码本身的性能也没去考虑过。主要是为了实现功能。

第一个循环是Laya默认从page中查询的逻辑,第二个是从我们定义的白名单中的查询逻辑,第三个循环是从bundle.js中查询的逻辑。

当我们没有白名单的时候即使选上了查询也不会进行查询,因此我们需要配置一个白名单,名字与代码中取的名字一样就行,我这里的名字叫做unusewhitelist.json,放到项目的根目录。

怎么移除项目中的yarn 删除项目_sed_02

这个白名单根据你自身的项目需求去配置文件名前缀后缀或者部分文件名都可以。

输出查询日志

既然都修改了代码了,我们就完成最后一步,将我们查询日志输出到项目根目录中,之前在Laya中我们查询是没办法将查询结果选中的,因此我们可以将其结果输出到一个文件中,供我们参考。这一步就要回到我们的查询结果之后去处理。修改onFindBtnClick函数。

__proto.onFindBtnClick=function(e){
	this.resultBox.visible=true;
	this._arr=ResManager.findUnUsed(this.depthCheck.selected,this.whiteListCheck.selected);
	this.msgTxt.text=Sys.lang("共找到 {0} 个资源",this._arr.length);
	this.checkSelectAll.selected=true;
	this.onCheckSelectAllChange(null);
	this.checkSelectAll.on("change",this,this.onCheckSelectAllChange);
	//将结果输出
	FileManager.createJSONFile(FileManager.getWorkPath("") + "\\finunusedLog.json",this._arr);
}

这里我们将查询结果输出到了项目根目录下的finunuseLog.json文件中供我们参考查询。至此我们所有功能已经实现。如果你觉得还不够可以自行修改来满足自己的功能。下面我们来比较下查询结果与之前的不同。


怎么移除项目中的yarn 删除项目_删除未引用资源_03

未使用我们修改的查询结果

怎么移除项目中的yarn 删除项目_sed_04

使用了我们修改的结果

由上面结果可见,我们代码中还有很多动态引用图片资源的代码,这样修改之后就敢放心大胆的删除不需要的资源了。