You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何更高效地在HTML中加载资源:基于JavaScript的HTML游戏Zip资源非单行加载优化

高效加载Zip资源的替代方案

你当前把整个Zip资源编码成base85塞进<script type="p4-project">的方式,确实会带来代码臃肿、加载解码开销大的问题。下面给你几个更合理的优化方案,从最优到过渡方案排序:

方案1:直接加载独立的Zip资源文件(推荐)

把游戏资源Zip作为单独的静态文件(比如game-assets.zip)放在服务器上,用fetch直接请求它,完全抛弃base85编码和script标签的方式。浏览器可以直接缓存Zip文件,加载速度更快,代码结构也更整洁。

修改你的getProjectData函数如下:

const getProjectData = (function() {
  const storage = scaffolding.storage;
  storage.onprogress = (total, loaded) => {
    setProgress(interpolate(0.75, 0.98, loaded / total));
  };
  storage.addHelper({
    load: (assetType, assetId, dataFormat) => zip.file(assetId + '.' + dataFormat)
      .async('uint8array')
      .then((data) => new storage.Asset(assetType, assetId, dataFormat, data))
  });
  return () => (async () => {
    // 替换成你的Zip资源实际URL
    const response = await fetch('game-assets.zip');
    const zipData = await response.arrayBuffer();
    
    zip = await Scaffolding.JSZip.loadAsync(zipData);
    return zip.file('project.json').async('arraybuffer');
  })();
})();

核心优势:

  • 消除base85编码/解码的额外性能开销
  • Zip文件可被浏览器缓存,重复访问加载更快
  • 主HTML不再被大量编码内容塞满,代码结构清晰
  • 能利用浏览器并行加载能力提升速度

方案2:资源清单+按需加载

如果游戏资源量很大,不需要一次性加载全部,可以先加载轻量的资源清单(比如asset-manifest.json),再根据游戏进度按需加载单个资源(可拆分多个小Zip或直接加载单个资源文件)。

示例实现步骤:

  1. 服务器放置asset-manifest.json,列出所有资源的路径、类型、ID
  2. 初始只加载清单,后续按需加载需要的资源

修改后的加载逻辑示例:

const getProjectData = async () => {
  // 先加载资源清单
  const manifestResp = await fetch('asset-manifest.json');
  const manifest = await manifestResp.json();
  
  // 加载核心的project.json
  const projectResp = await fetch(manifest.projectJsonPath);
  const projectData = await projectResp.arrayBuffer();
  
  // 配置storage为按需加载单个资源
  const storage = scaffolding.storage;
  storage.onprogress = (total, loaded) => {
    setProgress(interpolate(0.75, 0.98, loaded / total));
  };
  storage.addHelper({
    load: async (assetType, assetId, dataFormat) => {
      const asset = manifest.assets.find(a => a.id === assetId && a.format === dataFormat);
      if (!asset) throw new Error(`Asset ${assetId}.${dataFormat} not found`);
      
      const resp = await fetch(asset.path);
      const data = await resp.arrayBuffer();
      return new storage.Asset(assetType, assetId, dataFormat, new Uint8Array(data));
    }
  });
  
  return projectData;
};

核心优势:

  • 初始加载量极小,游戏启动速度更快
  • 避免加载当前不需要的资源,节省带宽和内存
  • 资源更新更灵活,无需重新打包整个Zip

方案3:过渡方案——将base85内容移到单独文件

如果暂时无法彻底修改架构,可以把base85编码内容单独存成文本文件(比如project-data.b85),用fetch加载它,至少能解决主HTML代码堆叠混乱的问题。

修改后的getProjectData函数:

const getProjectData = (function() {
  const storage = scaffolding.storage;
  storage.onprogress = (total, loaded) => {
    setProgress(interpolate(0.75, 0.98, loaded / total));
  };
  storage.addHelper({
    load: (assetType, assetId, dataFormat) => zip.file(assetId + '.' + dataFormat)
      .async('uint8array')
      .then((data) => new storage.Asset(assetType, assetId, dataFormat, data))
  });
  
  // 保留原base85解码逻辑
  const base85decode = e=>{const t=e=>(40===e&&(e=60),41===e&&(e=62),e-42),n=e.indexOf(","),c=+e.substring(0,n),o=new ArrayBuffer((s=c)%4==0?s:s+(4-s%4));var s;const a=new Uint32Array(o);for(let c=n+1,o=0;c<e.length;c+=5,o++)a[o]=85*t(e.charCodeAt(c+4))*85*85*85+85*t(e.charCodeAt(c+3))*85*85+85*t(e.charCodeAt(c+2))*85+85*t(e.charCodeAt(c+1))+t(e.charCodeAt(c));return new Uint8Array(o,0,c)};
  
  return () => (async () => {
    // 加载单独的base85文件
    const response = await fetch('project-data.b85');
    const base85Content = await response.text();
    
    const result = base85decode(base85Content);
    zip = await Scaffolding.JSZip.loadAsync(result);
    return zip.file('project.json').async('arraybuffer');
  })();
})();

核心优势:

  • 无需大幅修改现有解码逻辑
  • 主HTML恢复整洁,不再被大量编码内容占用
  • 单独的base85文件可被缓存,提升重复加载速度

内容的提问来源于stack exchange,提问作者Aurion games

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 09:12:35