前言
本文多数经验来自H5游戏(three.js + dom)开发。
我认为优化不单是代码写的更好,任务调度更合理。优化的目的是让使用者觉得更快、更流畅、更自然。
优化方案
js代码压缩
道理都懂,减少体积,减少解析时间。一般发布版使用压缩后的代码。推荐库 UglifyJS。
配置表
配置表一般都有较强的结构和语义,我们可以生成结构配置,极大减少无用重复字节。比如武将表
export default {
10001:{
name: '@name10001',
sid: 10001,
country: 1,
hp: 3000,
buff: '@buff201',
price: 30000,
chip: 80,
icon: 'texture/hero/10001.png',
module: '@module10001',
favor: 86,
attr1: 40001,
attr2: 40002,
...
},
10002:{
name: '@name10002',
sid: 10002,
country: 1,
hp: 3000,
buff: '@buff202',
price: 30000,
chip: 80,
icon: 'texture/hero/10002.png',
module: '@module10002',
favor: 86,
attr1: 40011,
attr2: 40012,
...
}
...
}
下面是简单处理。使用class生成实例更好,性能更好,效率更高
const attrs = ['name','sid','country','hp','buff','price','chip','icon','module',...]
const hero = {
10001:['@name10001', 10001, 1, 3000, '@buff201', 30000, 80, 'texture/hero/10001.png', '@module10001', 86, 40001, 40002,...],
10002:['@name10002', 10002, 1, 3000, '@buff202', 30000, 80, 'texture/hero/10002.png', '@module10002', 86, 40011, 40012,...],
...
}
const heroMap = new Map();
export const getInfo = function(sid) {
if(heroMap.has(sid)) {
return heroMap.get(sid);
}
const info = {};
for(let i = 0;i<attrs.length;i++){
info[attrs[i]] = hero[sid][i]
}
heroMap.set(sid,info);
return info;
}
css压缩
我们开始并没有对css做处理,但后来我们的界面全部采用工具生成,重复属性极多,比如position:absolute, flex-wrap:wrap等。如果建立映射,则只需要[p,1]就可替代。当然需要底层配合修改。
图片压缩
先推荐一下 imagemin 这个库。imagemin github
针对不同平台最好使用不同压缩方式。或者说如果浏览器支持 webp ,就优先使用它(png-webp减少80%)。
- jpeg,png -> webp:
imagemin-webpwebp的压缩基本都一样,没什么好选的。 - jpeg:
imagemin-mozjpeg记得做调研时发现squoosh在线转换使用的mozjpeg 压缩质量/体积比更高(-20%以上),忘记了为什么最终没用这个。有兴趣的可以去扒一下他们的代码。 - png:
imagemin-optipngimagemin-pngquant前者较均衡(画质几乎看不到损失的情况下占用存储更小),推荐使用。后者压缩体积效果更佳,但渐变色的地方会出现条纹。
项目未使用gif,故不作建议。
图片尽可能都压缩一遍,以防出现一个icon几十M的情况。
字体精简
使用 fontcreator 打开一个字体文件,你会发现字体库是有限个字符的矢量图构成,这也就意味着:
- 用不到的文字会占用多余的空间。
- 字库越个性占用空间越大。
第一个可以优化的点就是删除无用字符,比如伤害的漂字,我们只需要数字,剔除除 012345789. 外的字符占用仅几kb。
精简工具:fontmin
第二个可以优化的点是尽量选用选用轮廓较少的字(横平竖直的一般会少一些)。这一条主要针对的是常用字库,因为量大,一般5000字+
另外,使用woff 而非 ttf。见 developer.mozilla.org/zh-CN/docs/…
音频压缩
可以合并声道,一定范围内降低音质。
减请求数
我们的下载是将当前所需文件打包成一个文件下载,然后根据打包时的信息分割,减少下载时间。但是后来我注意到,进入游戏后在network面板依然看到800多个请求!原来我们对js和图片预加载使用的 blobURL 受请求数量限制,而每一个请求的发起都有等待时间,查看详细请求时间的描述。
- 代码合并加载:可以在打包时就分割模块,合并到同一文件,也可以加载js前将多个Buffer合并在创建blobUrl。
- 图片合并:可使用图片合并的库,将较小图片合并,并生成uv映射表。
这一条是相当重要,也是不容易优化的地方。上面提到的仅仅是我们的开发环境,针对各自的环境,可根据上面的链接查看请求耗时的地方进行优化。
避免有交互和更新时对磁盘的操作
这里的磁盘操作是指向 IndexDB 中写入数据。不过这个呢,取决于磁盘性能,现在市面上新发布的手机在这点上倒是不用担心了。
其他字节数据
约定格式,剔除无用数据。
分配用户时间
举个很简单的例子:
游戏loading界面一张图加一个读条本就算完成了,但策划会让加些tips和特效,这就是转移用户注意力,不会想着等了多少秒。
进入首界面,只加载核心内容,可以先闪一个log(1s),一个跑得飞快的进度条(1s),进度条结束等待0.5s,时间过去了快3s,但用户不觉得有等待。然后弹一个公告,手速再快关闭也需要1s,重要信息高亮提示,增加用户停留时间。再点击登录(0.5s),再给一个正常的读条。实际游戏加载已经过去了6s,而用户不会觉得有等待,但若是黑屏6s呢?
分配不是占用,尽量少让读条占用时间,因为用户并不需要读条。
优化内存
待续