在白鷺引擎發布了5.2.7版本中新增加了命令行,增加自動合圖插件TextureMergerPlugin功能。今天,我們以一個EUI案例來展示自動合圖插件的具體使用方法和注意事項。
此外,我們在本文還融入了UglifyPlugin、ResSplitPlugin、ZipPlugin等插件使用方法。開發者利用上述4款插件,將實現代碼包體積更小、更好管理的目標。
目錄:
使用UglifyPlugin將代碼混淆壓縮
使用ResSplitPlugin把部分資源分離出去
使用ZipPlugin把文件壓縮成zip格式
使用TextureMergerPlugin將紋理合并,且用ConvertResConfigFilePlugin修改res.json配置文件
項目初始化
data-scale-mode
改成fixedWidth
使用UglifyPlugin壓縮代碼
在微信開發者工具可以看到,js文件夾中5個庫文件和一個main.js
。
現在需求是是要把庫文件壓縮到一個文件lib.min.js
中。
回到EgretWing,編輯sctipts下的config.wxgame.ts:
//***其他代碼***
//
if (command == 'build') {
return {
outputDir,
commands: [
// 清理js,resource文件夾
new CleanPlugin({ matchers: ["js", "resource"] }),
new CompilePlugin({ libraryType: "debug", defines: { DEBUG: true, RELEASE: false } }),
new ExmlPlugin('commonjs'), // 非 EUI 項目關閉此設置
new WxgamePlugin(),
// 壓縮插件
new UglifyPlugin([
{
// 需要被壓縮的文件
sources: [
"libs/modules/egret/egret.js",
"libs/modules/eui/eui.js",
"libs/modules/assetsmanager/assetsmanager.js",
"libs/modules/tween/tween.js",
],
// 壓縮后的文件
target: "lib.min.js"
}
]),
new ManifestPlugin({ output: 'manifest.js' })
]
}
}
//
// ***其他代碼***
保存后在終端執行:egret build
可以在微信開發者工具看到發布后的代碼,js文件夾內的庫文件已經被壓縮到lib.min.js。
但是報錯,找不到eui,這是因為自動生成的manifest.js
里面對js的引用順序出錯,需要優先引用lib.min.js
打開根目錄下的manifest.js
, 修改一下引用順序。
require("js/lib.min.js")
require("js/main.js")
require("js/default.thm.js")
每次編譯的時候manifest.js
都會被重新生成,所以我們使用一個自定義腳本來修改他們的順序
打開 scripts下的myPlugin.ts :
/**
* 示例自定義插件,您可以查閱 http://developer.egret.com/cn/2d/projectConfig/cmdExtensionPluginin/
* 了解如何開發一個自定義插件
*/
export class CustomPlugin implements plugins.Command {
private buffer
constructor() {
}
async onFile(file: plugins.File) {
// 保存manifest.js文件的內容
if(file.basename.indexOf('manifest.js') > -1) {
this.buffer = file.contents
}
return file;
}
async onFinish(commandContext: plugins.CommandContext) {
// 把'lib.min.js'移到第一位
if (this.buffer) {
let contents: string = this.buffer.toString()
let arr = contents.split('\n')
let lib = null
arr.forEach((item, index) => {
if (item.indexOf('lib.min.js') > -1) {
lib = item
arr.splice(index, 1)
}
})
if (lib != null) {
arr.unshift(lib)
}
let newCont = arr.join('\n')
commandContext.createFile('manifest.js', new Buffer(newCont))
}
}
}
這個文件就是用來自定義插件的,在config.wxgame.ts中已經默認引用,所以只需要調用即可,注意調用順序
new ManifestPlugin({ output: 'manifest.js' }),
// 在manifest.js生成之后調用
new CustomPlugin()
使用ResSplitPlugin分離資源文件
因為微信對代碼包的大小是有限制的,總大小不能超過4M(使用分包功能可以提升到8M),所以我們需要通過ResSplitPlugin把某些游戲資源文件分離出去,將游戲資源放置在一個外部CDN服務器上,需要的時候動態加載即可。
編輯config.wxgame.ts:
// ***其他代碼***
//
new ResSplitPlugin({
verbose: false, matchers:
[
// from 使用glob表達式來匹配文件, projectName就是項目的名字
{ from: "resource/art/about/**.**", to: `${projectName}_wxgame_remote` },
{ from: "resource/art/heros_goods/**.**", to: `${projectName}_wxgame_remote` }
]
})
// ***其他代碼***
保存后在終端執行:
egret build
微信開發者工具中resource > art 下的about
和heros_goods
已經不在了。
被分離出去的在項目根目錄中 egret-eui-demo_wxgame_remote
文件夾內。
使用ZipPlugin把文件壓縮成zip格式
為了減少加載次數和傳輸量,我們可以把文件壓縮成zip格式,使用的時候可以使用第三方庫JSZip來讀取使用zip文件。
使用ZipPlugin插件之前,需要安裝cross-zip 和 cross-zip-cli , 在終端中輸入:
//全局安裝
npm install cross-zip -g
npm install cross-zip-cli -g
安裝完成之后,在config.wxgame.ts添加代碼:
new ZipPlugin({
mergeSelector: p => {
// 如果文件是assets/路徑下的, 壓縮到assets.zip
if (p.indexOf("assets/") >= 0) {
return "assets.zip"
}
}
})
項目中其實assets里面的資源都是沒有用到的,這里我們用它來演示壓縮插件的使用。
保存后在終端執行:
egret build
執行之后可以在微信開發者工具看到,resource目錄下原來的assets文件夾已經被壓縮成了assets.zip。
使用TextureMergerPlugin,ConvertResConfigFilePlugin合并紋理集
項目中使用的圖片資源都是單獨的png文件,在加載的時候每張圖片都會單獨請求。我們可以通過合并紋理集的方式把這些圖片合成一張圖,以減少請求數量。
使用插件之前,我們需要有紋理集的配置文件tmpropject
, 可以用兩種方式生成:
這里使用第二種方法,使用腳本autoMerger.js:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var fs = require("fs");
var path = require("path");
var resjsons = ["resource/default.res.json"]; //要掃描的res.json文件
var targetDir = "resource/TextureMerger"; //輸出目錄
var pathNor = path.relative(targetDir, "resource"); //返回一個相對路徑
var tempindex = 0;
//創建輸出文件夾
if (resjsons.length > 0) {
if (!fs.existsSync(targetDir)) {
// var paths = path.normalize(targetDir).split("\\"); //windows 下使用
var paths = path.normalize(targetDir).split("\/"); //mac linux 下使用
var target = ".";
for (var _i = 0, paths_1 = paths; _i < paths_1.length; _i++) {
var p = paths_1[_i];
// target += ("\\" + p); // windows 下使用
target += ("\/" + p); // mac linux 下使用
if (!fs.existsSync(target))
// 根據路徑創建文件夾
fs.mkdirSync(target);
}
}
}
var _loop_1 = function (resJson) {
// 判斷是否是res.json文件
if (fs.existsSync(resJson) && resJson.indexOf("res.json") > -1) {
var defaultJson = fs.readFileSync(resJson, "utf-8");
// 解析res.json文件內容
var defaultObject = JSON.parse(defaultJson);
var groups = defaultObject.groups; //組
var resources = defaultObject.resources; //資源
var resourcesHash_1 = {}; // 用來存放resources的資源信息
// 遍歷resources
for (var _i = 0, resources_1 = resources; _i < resources_1.length; _i++) {
var resource = resources_1[_i];
resourcesHash_1[resource.name] = resource.url;
}
// 遍歷groups
for (var _a = 0, groups_1 = groups; _a < groups_1.length; _a++) {
var group = groups_1[_a];
var tmproject = {}; //用來存放tmproject文件的信息
// tmproject文件配置
tmproject["options"] = {
"layoutMath": "2",
"sizeMode": "2n",
"useExtension": 1,
"layoutGap": 1,
"extend": 0
};
// projectName
tmproject["projectName"] = group.name + "_" + tempindex;
// 版本
tmproject["version"] = 5;
tempindex++;
// 獲取res.json分組的keys, 并分割成數組
var oldkeys = group.keys.split(",");
var oldkeysHash = {};
// 遍歷oldkeys
for (var _b = 0, oldkeys_1 = oldkeys; _b < oldkeys_1.length; _b++) {
var key = oldkeys_1[_b];
// 保存到oldkeysHash對象中
oldkeysHash[key] = true;
}
var newKeys = [];
// 遍歷oldkeys
for (var _c = 0, oldkeys_2 = oldkeys; _c < oldkeys_2.length; _c++) {
var key = oldkeys_2[_c];
if (key.indexOf("json") == -1) {
if (!oldkeysHash[key.replace("png", "json")]) { //粒子和龍骨對應的圖集不合圖
if (!oldkeysHash[key.replace("png", "fnt")]) //位圖字體
newKeys.push(key);
}
else if (key.indexOf("jpg") > -1) {
newKeys.push(key);
}
}
}
oldkeysHash = {};
oldkeys = [];
// files路徑
var urls = newKeys.map(function (key) {
return path.join(pathNor, resourcesHash_1[key]);
});
tmproject["files"] = urls;
// 根據tmproject寫入文件
if (urls.length > 0) {
fs.writeFileSync(path.join(targetDir, tmproject["projectName"] + ".tmproject"), JSON.stringify(tmproject));
}
tmproject = {};
}
}
};
//根據數組開始掃描
for (var _a = 0, resjsons_1 = resjsons; _a < resjsons_1.length; _a++) {
var resJson = resjsons_1[_a];
_loop_1(resJson);
}
把這個腳本放在scripts文件夾內,這個腳本是根據項目的default.res.json
文件的內容來生成tmpropject
文件
在終端中執行:
node scripts/autoMerger.js
執行成功之后可以在resource文件夾中看到多出了一個TextureMerger文件夾,里面就是根據default.res.json
分組生成的tmpropject
文件。
現在只需要執行TextureMergerPlugin插件就可以自動合并,這里需要注意TextureMergerPlugin依賴 TextureMerger 1.7 以上的版本,如果不符合請自行安裝,并且在運行時TextureMerger需要處于關閉狀態。
new TextureMergerPlugin({textureMergerRoot:[ 'resource']})
保存后在終端執行:
egret build
執行完成后,在微信開發者工具可以看到,resource > TextureMerger 內新增了三個png文件,就是合并之后的紋理集。游戲運行的時候只需要加載這三個紋理集就可以,無需加載那些單獨的png文件但是需要去res.json里面配置,把單獨的資源引用都刪除,加上紋理集的引用。
這些操作當然不需要手動去完成,現在只需要使用ConvertResConfigFilePlugin插件就可以實現這個功能。
編輯config.wxgame.ts:
new TextureMergerPlugin(),
new ConvertResConfigFilePlugin({
resourceConfigFiles: [{ filename: "resource/default.res.json", root: "resource/" }],
nameSelector: (p) => {
return path.basename(p).split(".").join("_")
},
TM_Verbose: true
})
保存后在終端執行:
egret build
在微信開發者工具中,打開調試器,在network面板可以看到加載的紋理集。
這里有個注意事項,在游戲中點擊英雄按鈕,切換到英雄場景時,會發現列表里面的圖片加載不出來。
在network面板可以看到加載請求是單獨的png文件,而不是紋理集。
這是因為列表中的圖片地址是直接使用url。
// 原始數組
let dataArr:any[] = [
{image: 'resource/art/heros_goods/heros01.png', name: '亞特伍德', value: '評價: 很特么厲害, 為所欲為', isSelected: false},
{image: 'resource/art/heros_goods/heros02.png', name: '亞特伍德', value: '評價: 很特么厲害, 為所欲為', isSelected: false},
{image: 'resource/art/heros_goods/heros03.png', name: '亞特伍德', value: '評價: 很特么厲害, 為所欲為', isSelected: true},
{image: 'resource/art/heros_goods/heros04.png', name: '亞特伍德', value: '評價: 很特么厲害, 為所欲為', isSelected: false},
{image: 'resource/art/heros_goods/heros05.png', name: '亞特伍德', value: '評價: 很特么厲害, 為所欲為', isSelected: false},
{image: 'resource/art/heros_goods/heros06.png', name: '亞特伍德', value: '評價: 很特么厲害, 為所欲為', isSelected: false},
{image: 'resource/art/heros_goods/heros07.png', name: '亞特伍德', value: '評價: 很特么厲害, 為所欲為', isSelected: false}
]
// 轉成eui數據
let euiArr:eui.ArrayCollection = new eui.ArrayCollection(dataArr)
// 把list_hero數據源設置成euiArr
this.list_hero.dataProvider = euiArr
// 設置list_hero的項呈視器 (這里直接寫類名,而不是寫實例)
this.list_hero.itemRenderer = heroList_item
這種引用方式的圖片,需要開發者手動在代碼中修改,將圖片地址修改成紋理集中的圖片。
結語
本文通過使用UglifyPlugin,ResSplitPlugin,ZipPlugin,TextureMergerPlugin,ConvertResConfigFilePlugin插件,使項目發布到微信小程序之后的代碼包體積減小,用戶發起的請求數變少,且將代碼混淆壓縮。
使用Egret自帶的插件,已經可以滿足開發者的基本需求,如果有針對項目的特殊需求,可以選擇自定義插件。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。