Cocos Creator—最佳構(gòu)建部署實(shí)踐

這篇文章主要是我們團(tuán)隊(duì)在使用Cocos Creator過程中的一些關(guān)于部署方面的實(shí)踐總結(jié)缴守,標(biāo)題黨了一回,嚴(yán)格來說处面,應(yīng)該是《快看漫畫游戲研發(fā)團(tuán)隊(duì)使用Cocos Creator構(gòu)建部署最佳實(shí)踐》嫩海,對(duì)于其他團(tuán)隊(duì)可能并不是。

之所以寫這篇文章霎烙,一是我剛開始接觸Cocos Creator的時(shí)候,發(fā)現(xiàn)構(gòu)建部署方面的一些問題,針對(duì)性寫了3篇優(yōu)化的方案悬垃,隨著對(duì)Cocos Creator了解的深入游昼,我發(fā)現(xiàn)了一些更好的替代方法,二是因?yàn)槲覀儓F(tuán)隊(duì)隨著業(yè)務(wù)發(fā)展尝蠕,又到了缺人的時(shí)候烘豌,出來刷刷臉,發(fā)點(diǎn)招聘廣告:Cocos Creator工程師快到碗里來看彼。

不過你不用擔(dān)心廊佩,本文不會(huì)只是炒炒冷飯,這次涉及的內(nèi)容覆蓋了構(gòu)建部署的整個(gè)環(huán)節(jié)靖榕,如果你剛好把代碼寫好了标锄,你應(yīng)該看看本文,它會(huì)告訴你怎么把你的代碼漂亮的部署到線上茁计,并且這里涉及的代碼你都可以通過github查看料皇。涉及知識(shí)點(diǎn)如下:

  1. 如何自定義loading頁面
  2. 圖片部署自動(dòng)化壓縮優(yōu)化
  3. 減少loading頁面出現(xiàn)之前的白屏?xí)r間
  4. 代碼混淆與保護(hù)
  5. 文件資源增加md5版本號(hào)
  6. cdn緩存

由于我們游戲采用的是1.6版本,所以還保留了md5版本號(hào)的優(yōu)化星压,新的1.7版本已經(jīng)比較完美支持md5的功能践剂,但由于沒有在實(shí)踐中使用,所以還是基于1.6版本做一次總結(jié)租幕,本質(zhì)是一樣的舷手。

本篇我們會(huì)基于Cocos Creator的官方示例做分析,我在原demo的基礎(chǔ)上增加了部署的腳本劲绪,部署到又拍云和騰訊云男窟。為了展示自定義loading頁面的功能,我把這個(gè)游戲的loading頁面改了贾富,如果有問題歉眷,麻煩官方聯(lián)系我下架。

1. 如何自定義loading頁面

這個(gè)需求官方其實(shí)是有提供解決方案的颤枪,官方文檔-“定制項(xiàng)目構(gòu)建模板”的功能就可以實(shí)現(xiàn)這個(gè)需求汗捡,可能是文檔描述得不太清楚,我當(dāng)時(shí)并沒有把這個(gè)功能跟“自定義加載首頁”聯(lián)系起來畏纲。

由于這個(gè)構(gòu)建模板功能扇住,我們就可以不用gulp插件輕松實(shí)現(xiàn)自定義首頁HTML,CSS,JS的功能了。怎么實(shí)現(xiàn)可以訪問本文的項(xiàng)目地址查看盗胀。

自定義loading頁面效果:

WX20171213-221317@2x.png

2. 圖片部署自動(dòng)化壓縮優(yōu)化

通過gulp工具艘蹋,在部署之前自動(dòng)化處理一遍圖片壓縮流程,在無損壓縮的情況下票灰,既能保證圖片的輸出質(zhì)量還能減少體積女阀。有團(tuán)隊(duì)會(huì)手動(dòng)采用tinypng或者其他壓縮工具提前壓縮宅荤,這樣做也是可以的,但流程不好把控浸策,原則上能自動(dòng)化處理的盡量讓機(jī)器來做冯键,人是會(huì)累的但機(jī)器不會(huì),也不會(huì)出錯(cuò)庸汗。

var imagemin = require("gulp-imagemin");
gulp.task("imagemin", function (cb) {
    gulp.src(["./build/web-mobile/**/*.png"])
        .pipe(imagemin([
            imagemin.gifsicle({interlaced: true}),
            imagemin.jpegtran({progressive: true}),
            imagemin.optipng({optimizationLevel: 5})
        ]))
        .pipe(gulp.dest("./build/web-mobile/"))
        .on("end", cb);
});`

3. 減少loading頁面出現(xiàn)之前的白屏?xí)r間

通過gulp-htmlmin插件惫确,把首屏的js,css文件合并到首頁html文件蚯舱,能有效減少網(wǎng)絡(luò)不穩(wěn)定情況下進(jìn)入游戲白屏的時(shí)間雕薪。

var htmlmin = require("gulp-htmlmin");
gulp.task("htmlmin", ["imagemin"], function (cb) {
    gulp.src("./build/web-mobile/*.html")
        .pipe(fileInline())
        .pipe(htmlmin({
            collapseWhitespace: true,
            removeComments: true,
            minifyCSS: true
        }))
        .pipe(gulp.dest("./build/web-mobile/")
            .on("end", cb));
});

通過合并操作,首屏loading頁面只需要加載index.html文件晓淀,在304情況下白屏?xí)r間只有142ms!

WX20171214-101911@2x.png

4. 代碼混淆盏档,代碼保護(hù)

Cocos Creator引擎build后會(huì)對(duì)代碼進(jìn)行壓縮優(yōu)化凶掰,但通過強(qiáng)大的chrome工具格式化代碼后,還是能輕松閱讀代碼的整體邏輯蜈亩,在競(jìng)爭(zhēng)激烈的游戲行業(yè)懦窘,代碼保護(hù)力度是不足夠的。由于代碼暴露在前端稚配,H5游戲不存在加密可言畅涂,但我們可以做一些工作,增加游戲被破解盜竊的難度道川。

gulp-javascript-obfuscator插件可以對(duì)代碼進(jìn)行可讀性混淆午衰,禁止開啟chrome調(diào)試,域名綁定等功能冒萄,能很大程度保護(hù)自己的代碼臊岸,這個(gè)插件還有其他很強(qiáng)大的功能,有興趣可以訪問github了解尊流。但我不建議開啟太多功能帅戒,畢竟對(duì)性能還是有一定影響。

var javascriptObfuscator = require("gulp-javascript-obfuscator");
gulp.task("obfuscator", ["htmlmin"], function (cb) {
    gulp.src(["./build/web-mobile/project.js"])
        .pipe(javascriptObfuscator({
            compact: true,
            domainLock: [".zz-game.com"],
            mangle: true,
            rotateStringArray: true,
            selfDefending: true,
            stringArray: true,
            target: "browser"
        }))
        .pipe(gulp.dest("./build/web-mobile")
            .on("end", cb));
});

我采用了最輕量的混淆方案崖技,混淆前后對(duì)比:

混淆前:

TabCtrl: [function(t, e, i) {
        "use strict";
        cc._RF.push(e, "62208XJq9ZC2oNDeQGcbCab", "TabCtrl"),
        cc.Class({
            extends: cc.Component,
            properties: {
                idx: 0,
                icon: cc.Sprite,
                arrow: cc.Node,
                anim: cc.Animation
            },
            init: function(t) {
                this.sidebar = t.sidebar,
                this.idx = t.idx,
                this.icon.spriteFrame = t.iconSF,
                this.node.on("touchstart", this.onPressed.bind(this), this.node),
                this.arrow.scale = cc.p(0, 0)
            }
        }),
        cc._RF.pop()
    }
    , {}]
}, {}, ["ItemList", "ItemTemplate", "BackPackUI", "ButtonScaler", "ChargeUI", "EnergyCounter", "HeroSlot", "HomeUI", "PanelTransition", "ShopUI", "SubBtnsUI", "MainMenu", "MenuSidebar", "TabCtrl"]);

混淆后:

'l': [function(b, a, c) {
        'use strict';
        cc[_0xc008('0x12')][_0xc008('0x13')](a, _0xc008('0x98'), 'l'),
        cc['T']({
            'S': cc['U'],
            'O': {
                'idx': 0x0,
                'icon': cc[_0xc008('0x3e')],
                'arrow': cc['Node'],
                'anim': cc['Animation']
            },
            '_': function(a) {
                this[_0xc008('0x68')] = a[_0xc008('0x68')],
                this['idx'] = a[_0xc008('0x7b')],
                this[_0xc008('0x66')][_0xc008('0x47')] = a[_0xc008('0x65')],
                this[_0xc008('0x1b')]['on'](_0xc008('0x99'), this[_0xc008('0x9a')][_0xc008('0x5e')](this), this[_0xc008('0x1b')]),
                this[_0xc008('0x9b')][_0xc008('0x9c')] = cc['p'](0x0, 0x0);
            }
        }),
        cc[_0xc008('0x12')][_0xc008('0x20')]();
    }
    , {}]
}, {}, ['i', 'd', 'f', 'c', 'j', 'b', 'h', 'n', 'a', 'm', 'g', 'k', 'e', 'l']);

在不影響性能的前提下逻住,稍微做一些代碼保護(hù),還是不錯(cuò)的迎献。如果你想讓代碼更惡心一點(diǎn)也是可以的:

a.DFsJp;
        cc[a[_0xc91c('0x43a')](_0x490d30, a[_0xc91c('0x43b')])][a[_0xc91c('0x43c')](_0x490d30, _0xc91c('0xe5'))](b, a[_0xc91c('0x43c')](_0x490d30, a['\x68\x6d\x41\x4c\x54']), '\x6c'),
        cc['\x54']({
            'S': cc['\x55'],
            'O': {
                'idx': 0x0,
                'icon': cc[_0x490d30(_0xc91c('0x249'))],
                'arrow': cc['\x4e\x6f\x64\x65'],
                'anim': cc[a[_0xc91c('0x43d')]]
            },
            '_': function(b) {
                this[a[_0xc91c('0x43e')](_0x490d30, _0xc91c('0x31c'))] = b[a[_0xc91c('0x43e')](_0x490d30, '\x30\x78\x36\x38')],
                this[a[_0xc91c('0x43f')]] = b[_0x490d30(a[_0xc91c('0x440')])],
                this[_0x490d30(a[_0xc91c('0x441')])][_0x490d30(a['\x6b\x77\x71\x63\x72'])] = b[_0x490d30(a[_0xc91c('0x442')])],
                this[_0x490d30(_0xc91c('0x1c0'))]['\x6f\x6e'](a[_0xc91c('0x43e')](_0x490d30, a[_0xc91c('0x443')]), this[a['\x45\x79\x7a\x47\x44'](_0x490d30, a['\x6a\x64\x44\x61\x6e'])][_0x490d30(_0xc91c('0x2e0'))](this), this[a[_0xc91c('0x444')](_0x490d30, _0xc91c('0x1c0'))]),
                this[a[_0xc91c('0x445')](_0x490d30, _0xc91c('0x446'))][a[_0xc91c('0x445')](_0x490d30, a[_0xc91c('0x447')])] = cc['\x70'](0x0, 0x0);

開啟debugProtection功能:

image.png

打開chrome調(diào)試工具就會(huì)觸發(fā)無限循環(huán)的dubugger瞎访,讓chrome調(diào)試工具無法使用,增大破解難度忿晕。為了方便大家查看學(xué)習(xí)demo装诡,線上版本我關(guān)閉了這個(gè)選項(xiàng)银受。

開啟disableConsoleOutput功能:

image.png

禁止console.log功能,很多混淆代碼鸦采,通過斷點(diǎn)+console.log宾巍,可以方便把翻譯后的代碼輸出,開啟disableConsoleOutput渔伯,同樣增加調(diào)試難度顶霞。為了把我們的廣告無處不在,我同樣把它關(guān)了锣吼。JavaScript obfuscator還有其他不錯(cuò)的功能选浑,這里不再展開。

5. 文件資源增加md5版本號(hào)

版本號(hào)的方案跟之前的文章基本一致玄叠,這個(gè)流程在1.7版本應(yīng)該可以忽略了古徒。

gulp.task("resRev", ["obfuscator"], function (cb) {
    gulp.src(["./build/web-mobile/**/*.js", "./build/web-mobile/*.png"])
        .pipe(rev())
        .pipe(gulp.dest("./build/web-mobile/"))
        .pipe(rev.manifest())
        .pipe(gulp.dest("./build/web-mobile/")
            .on("end", cb));
});
gulp.task("default", ["resRev"], function (cb) {
    del(["./build/web-mobile/src"]);
    gulp.src(["./build/web-mobile/*.json", "./build/web-mobile/index.html"])
        .pipe(revCollector())
        .pipe(gulp.dest("./build/web-mobile/"));
    gulp.src(["./build/web-mobile/*.json", "./build/web-mobile/main*.js"])
        .pipe(revCollector({
            replaceReved: true
        }))
        .pipe(gulp.dest("./build/web-mobile/")
            .on("end", cb));
});

通過md5+強(qiáng)緩存,第二次加載基本是毫秒級(jí)读恃,瞬開隧膘。

116個(gè)請(qǐng)求的頁面,只需要109ms就能渲染出loading頁面寺惫,完全加載所有資源只需要1.25s:

image.png

6. cdn緩存

最后是把代碼部署到cdn疹吃,現(xiàn)在的云服務(wù)都提供cdn分發(fā)的功能,通過簡單配置西雀,我相信你能折騰出來的萨驶,所以不再贅述。

這里主要做不同方案的演示艇肴,我部署了兩個(gè)方案:直接回源和cdn分發(fā)腔呜。

首次訪問

在Wifi網(wǎng)絡(luò)下,回源方案耗時(shí)6-10s再悼,cdn分發(fā)方案耗時(shí)3-6s育谬。

第二次訪問

由于增加了強(qiáng)緩存,無論是cdn還是回源帮哈,第二次訪問時(shí)間都在1-2s之間膛檀。

這個(gè)項(xiàng)目本身存在先天不足,例如圖片沒有合并娘侍,導(dǎo)致首次請(qǐng)求有116個(gè)咖刃,加載速度肯定會(huì)受影響。但通過cdn緩存方案憾筏,也能基本保證快速加載嚎杨。

又拍cdn方案:

image.png

騰訊回源方案:

image.png

代碼我已經(jīng)部署到了又拍云和騰訊云,大家可以點(diǎn)擊訪問感受加載速度氧腰。

直接回源的部署方案枫浙,點(diǎn)擊訪問

采用cdn等優(yōu)化方案刨肃,點(diǎn)擊訪問

cdn是比較好的優(yōu)化首次訪問網(wǎng)絡(luò)速度的方案,但cdn也不是必然比源站快箩帚,大家測(cè)試時(shí)發(fā)現(xiàn)回源更快也不必驚訝真友,本質(zhì)上cdn節(jié)點(diǎn)就是距離你更近的代理服務(wù)器,但也有很多情況導(dǎo)致cdn緩慢紧帕,所以部署后還要通過工具多測(cè)試各個(gè)cdn節(jié)點(diǎn)的狀況盔然。

最后

游戲優(yōu)化肯定不僅僅這幾條,有很多優(yōu)化要根據(jù)實(shí)際情況實(shí)際分析是嗜。但這6點(diǎn)實(shí)踐愈案,應(yīng)該可以解決論壇經(jīng)常提到的緩存刷新,加載速度等部署相關(guān)的問題鹅搪。

資源md5+cdn+強(qiáng)緩存 能解決80%H5游戲加載速度的問題站绪,特別是第二次訪問,2秒打開輕輕松松丽柿,基本已經(jīng)成為web前端優(yōu)化的工業(yè)標(biāo)準(zhǔn)方案崇众。但現(xiàn)在很多線上的H5游戲還有很多走url參數(shù)+時(shí)間戳/md5的老方案,這種方案有很多弊端航厚。希望通過本文,大家都能在自己的游戲內(nèi)把資源md5+cdn+強(qiáng)緩存的方案貫徹執(zhí)行起來锰蓬。其實(shí)很簡單幔睬,特別是Cocos Creator1.7版本后就更方便了。H5游戲的優(yōu)勢(shì)就是即點(diǎn)即玩芹扭,如果這點(diǎn)都做不到麻顶,就沒什么優(yōu)勢(shì)了。

說了這么多舱卡,你可能覺得實(shí)踐起來很麻煩辅肾,業(yè)務(wù)太多沒時(shí)間搞這些。

沒關(guān)系轮锥,本文買一送一矫钓,既然你看到這里,說明你也是有緣之人舍杜,我把代碼倉庫也贈(zèng)送給你新娜,例子源碼我放在了github cocos-fly上,有需要大家可以上去下載既绩。

把gulpfile.js和releash.sh扒下來概龄,只需要執(zhí)行命令:sh releash,就可以一鍵構(gòu)建出可發(fā)布的代碼饲握。

線上示例+源碼+教程一條龍私杜,還不趕緊引入自己的項(xiàng)目蚕键?。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末衰粹,一起剝皮案震驚了整個(gè)濱河市锣光,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌寄猩,老刑警劉巖嫉晶,帶你破解...
    沈念sama閱讀 221,888評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異田篇,居然都是意外死亡替废,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門泊柬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來椎镣,“玉大人,你說我怎么就攤上這事兽赁∽创穑” “怎么了?”我有些...
    開封第一講書人閱讀 168,386評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵刀崖,是天一觀的道長惊科。 經(jīng)常有香客問我,道長亮钦,這世上最難降的妖魔是什么馆截? 我笑而不...
    開封第一講書人閱讀 59,726評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮蜂莉,結(jié)果婚禮上蜡娶,老公的妹妹穿的比我還像新娘。我一直安慰自己映穗,他們只是感情好窖张,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蚁滋,像睡著了一般宿接。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辕录,一...
    開封第一講書人閱讀 52,337評(píng)論 1 310
  • 那天澄阳,我揣著相機(jī)與錄音,去河邊找鬼踏拜。 笑死碎赢,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的速梗。 我是一名探鬼主播肮塞,決...
    沈念sama閱讀 40,902評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼襟齿,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了枕赵?” 一聲冷哼從身側(cè)響起猜欺,我...
    開封第一講書人閱讀 39,807評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拷窜,沒想到半個(gè)月后开皿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,349評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡篮昧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評(píng)論 3 340
  • 正文 我和宋清朗相戀三年赋荆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片懊昨。...
    茶點(diǎn)故事閱讀 40,567評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡窄潭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出酵颁,到底是詐尸還是另有隱情嫉你,我是刑警寧澤,帶...
    沈念sama閱讀 36,242評(píng)論 5 350
  • 正文 年R本政府宣布躏惋,位于F島的核電站幽污,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏簿姨。R本人自食惡果不足惜距误,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望款熬。 院中可真熱鬧,春花似錦攘乒、人聲如沸贤牛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽殉簸。三九已至,卻和暖如春沽讹,著一層夾襖步出監(jiān)牢的瞬間般卑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評(píng)論 1 272
  • 我被黑心中介騙來泰國打工爽雄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蝠检,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,995評(píng)論 3 377
  • 正文 我出身青樓挚瘟,卻偏偏與公主長得像叹谁,于是被迫代替她去往敵國和親饲梭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容