字节小程序开发踩坑实录那些年遇到的诡异bug和解决方案

长孙夏沫 移动 阅读 1,102
赞 37 收藏
二维码
手机扫码查看
反馈

字节小程序里图片预览踩坑记

最近在做一个字节小程序,里面有个图片预览功能,结果被坑得够呛。本来以为就是个简单的previewImage,结果各种诡异问题。

字节小程序开发踩坑实录那些年遇到的诡异bug和解决方案

一开始按照官方文档写的:

wx.previewImage({
  current: url,
  urls: [url1, url2, url3]
})

本地测试没问题,一发布到线上就跪了。图片显示不出来,console也没报错,就是黑屏。折腾了半天才发现,字节小程序对图片格式的要求比微信小程序严格多了。

域名问题先解决了

这里我踩了个坑,之前在微信小程序里跑得好好的域名,到了字节小程序就不行了。字节小程序的网络请求必须配合法合规的HTTPS域名,而且还要在开发者后台配置业务域名。

在字节小程序后台找到设置-开发设置-服务器域名,把图片服务器域名加进去。这个步骤很多人容易忘,我也是后来才想起来。

图片格式问题才是大头

最恶心的是图片格式限制。字节小程序对webp格式支持很弱,我的图片都是webp格式的,结果预览就出问题。后来试了下发现png、jpg都没问题,唯独webp不行。

解决方法是做个兼容判断:

// 检查是否为webp格式
function checkWebPSupport() {
  const canvas = document.createElement('canvas');
  return canvas.toDataURL('image/webp').indexOf('image/webp') === 0;
}

// 图片预览兼容处理
function previewImage(currentUrl, urlList) {
  let processedUrls = [...urlList];
  
  // 如果是webp格式且不支持,尝试转为jpg
  if (currentUrl.includes('.webp') && !checkWebPSupport()) {
    processedUrls = processedUrls.map(url => {
      if (url.includes('.webp')) {
        return url.replace(/.webp$/, '.jpg');
      }
      return url;
    });
  }
  
  wx.previewImage({
    current: currentUrl.replace(/.webp$/, '.jpg'),
    urls: processedUrls
  });
}

其实这个检测函数在小程序环境里不一定好使,后来我发现还是得在数据层面做处理。

真正的解决方案

后来想了半天,决定在服务端接口返回的时候就把图片格式信息带上。这样前端可以根据设备能力动态选择合适的格式:

// 后端接口返回格式优化
{
  "images": [
    {
      "original": "https://example.com/image.webp",
      "fallback": "https://example.com/image.jpg", 
      "format": "webp"
    }
  ]
}

// 前端处理逻辑
function handleImagePreview(images, currentIndex) {
  const deviceInfo = wx.getSystemInfoSync();
  const isByteDance = deviceInfo.appName === 'Douyin';
  
  let previewUrls = images.map(img => {
    // 字节系APP优先使用jpg格式
    if (isByteDance && img.format === 'webp') {
      return img.fallback || img.original;
    }
    return img.original;
  });
  
  wx.previewImage({
    current: previewUrls[currentIndex],
    urls: previewUrls
  });
}

还有个奇葩问题

字节小程序里还有一个问题,就是当图片数组特别大的时候(比如超过50张),预览会卡顿甚至崩溃。这个问题我在调试工具里看不出来,真机测试才发现。

后来只能做个分批处理:

function batchPreviewImages(allImages, startIndex) {
  // 限制单次预览数量,避免内存溢出
  const MAX_PREVIEW_COUNT = 30;
  let previewImages = [];
  
  if (allImages.length > MAX_PREVIEW_COUNT) {
    const start = Math.floor(startIndex / MAX_PREVIEW_COUNT) * MAX_PREVIEW_COUNT;
    const end = Math.min(start + MAX_PREVIEW_COUNT, allImages.length);
    
    previewImages = allImages.slice(start, end);
    
    // 提示用户当前范围
    const currentIndexInBatch = startIndex % MAX_PREVIEW_COUNT;
    wx.showModal({
      title: '提示',
      content: 当前显示第${start + 1}-${end}张,共${allImages.length}张,
      showCancel: false
    });
  } else {
    previewImages = allImages;
  }
  
  wx.previewImage({
    current: previewImages[startIndex % MAX_PREVIEW_COUNT],
    urls: previewImages
  });
}

缓存策略也得考虑

图片预览的时候还要注意缓存问题。字节小程序的缓存机制跟微信不太一样,有时候图片更新了,但是缓存没刷新,用户看到的还是旧图。

我在URL后面加了时间戳参数:

function addTimestampToImageUrl(url) {
  const separator = url.includes('?') ? '&' : '?';
  return ${url}${separator}t=${Date.now()};
}

// 预览前处理URL
function preparePreviewUrls(imageList) {
  return imageList.map(url => {
    if (isByteDanceApp()) {
      return addTimestampToImageUrl(url);
    }
    return url;
  });
}

不过这种方式会导致图片每次都重新加载,体验不太好。最后我还是选择了按需刷新的策略,只有在特定场景下才加时间戳。

一些注意事项

踩坑提醒:这三点一定注意

  • 1. 图片域名必须配置到字节小程序后台的服务器域名列表
  • 2. webp格式支持不稳定,最好准备备用格式
  • 3. 大量图片预览要做分页处理,不然容易卡死

另外,字节小程序的debug模式跟release模式表现还不一样,有些问题只有发包测试才能发现。这个问题困扰了我好久,后来每次修改都必须真机调试确认才行。

还有一个小细节,就是图片的宽高比。字节小程序在某些机型上预览图片时,缩放比例计算有问题,会出现拉伸变形的情况。我只能在上传的时候统一处理图片尺寸,尽量保持一致的比例。

总结

总体来说,字节小程序的图片预览功能确实有不少坑要填。虽然API看起来跟微信一样,但实际上限制更多,兼容性要求更高。

以上是我踩坑后的总结,如果你有更好的方案欢迎评论区交流。毕竟字节小程序这块文档真的不够详细,很多问题都得自己摸索。

本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。
发表评论

暂无评论