环境:Three.js r160+ / Windows / Zipoly 桌面端 v2.1.0(Draco 引擎)。问题:H5 展示首屏 8s+,Network 定位到 46MB 的 GLB。处理流程记录如下,命令和代码都是可直接抄的。
步骤一:确认瓶颈
DevTools → Network → 按大小排序。GLB 排第一且 >5MB,坐实。顺便看下有没有 4K 贴图和未压缩 HDR 混进来——它们经常是共犯,别只盯着模型文件。
步骤二:压缩(Draco Level 7)
命令行方案是 gltf-pipeline:
gltf-pipeline -i model.glb -o model_out.glb --draco.compressionLevel 7
我用的是 Zipoly 桌面端(美术同事用不了命令行):模型优化页 → 引擎选 Draco → 强度 7 → 开始优化。结果:
输入 ShanDiChe.glb 10.6 MB
输出 ShanDiChe_optimized.glb 596 KB (-94.5%)
顶点 278,516 / 三角面 190,916 / 材质 20
官方提示: Web 端加载预计提速约 76%
注意:已压过的模型再跑 Meshopt 几乎无效(实测 846KB→815KB),别浪费时间。反过来,Meshopt 的场景图优化(合并网格实例降 Draw Call、保留命名节点)适合做完首压后的结构微调,两个引擎是配合关系不是替代关系。
步骤三:Three.js 配解码器(必做)
不配 decoder 直接黑屏,报错还不直观。完整代码:
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
const draco = new DRACOLoader();
draco.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.6/');
const loader = new GLTFLoader();
loader.setDRACOLoader(draco);
loader.load('model_optimized.glb', (gltf) => {
scene.add(gltf.scene);
});
decoder 也可以 npm 装 three/examples/jsm/libs/draco/ 后走本地路径,避免外链依赖。内网项目必须本地化,别指望用户环境能访问 gstatic。
步骤四:进度反馈
loader.load(url, onLoad, (e) => {
if (e.total) bar.style.width = `${(e.loaded / e.total) * 100}%`;
});
有进度条的三秒,比白屏的三秒体验好一档。这是交互设计常识,但十个项目九个忘。
步骤五:懒加载兜底
首屏只放主视角模型,其余 IntersectionObserver 触发再加载。模型压到 1MB 内还嫌慢的场景,就该上这招了——压缩解决「单个体积」,懒加载解决「总量」。
结果与坑
- 首屏 8s → 2s 内(46MB 源模型先在 Blender 里粗减面再压的)
- 坑 1:Draco 压完忘配解码器,黑屏查了半小时
- 坑 2:带骨骼动画的模型压缩收益波动大,先试压再批量
- 坑 3:老旧 WebView(无 WebGL2)环境先拿真机验证解码兼容
模型已经很低面数还嫌大?那是内容决定的,改做懒加载吧,别跟压缩较劲。有具体报错或参数疑问的,评论区丢出来一起看。