你肯定遇到过这种情况:在地铁上、电梯里,手机信号只有一格,打开一个小程序,转圈、白屏、提示“网络不给力”。用户等不了三秒就关掉了。

能不能让小程序在没有网络的时候也能打开,至少能看到之前看过的内容?答案是肯定的。今天聊聊小程序的网络请求优化和离线缓存策略。

先理解问题:小程序不是本地App

传统App安装后会占用几百MB空间,很多资源和数据都存在本地。小程序不同,它每次打开需要从服务器拉取代码包和业务数据。

这导致一个天然劣势:依赖网络。但反过来也给了我们一个机会——既然数据要拉取,我们可以设计一套策略,让小程序在弱网甚至无网时依然可用。

缓存的基本思路:先本地,后远程

核心原则只有一条:不要每次都去问服务器要数据

用户第一次打开小程序时,我们把数据存下来。第二次打开时,先展示本地数据,同时在后台偷偷去服务器拉取最新数据。用户感知不到等待。

这个思路在三个层面上可以实施。

层级一:Storage缓存业务数据

小程序提供了同步和异步的Storage API,可以把数据存在用户手机里。

javascript
// 保存数据
wx.setStorageSync('userInfo', { name: '张三', avatar: '...' })

// 读取数据
const userInfo = wx.getStorageSync('userInfo')
if (userInfo) {
  // 先展示缓存的数据
  this.setData({ userInfo })
}

// 然后在后台请求最新数据
wx.request({
  url: 'https://api.example.com/user/info',
  success: (res) => {
    this.setData({ userInfo: res.data })
    wx.setStorageSync('userInfo', res.data)
  }
})

但Storage有容量限制,单个小程序最大10MB。不能什么都往里存。

层级二:数据请求的强缓存策略

对于不太变化的数据,可以在后端接口响应头里加上Cache-Control。

后端返回示例:

text
Cache-Control: max-age=3600

小程序发起请求时,如果开启了forceUpdate,可以这样配置:

javascript
wx.request({
  url: 'https://api.example.com/config',
  enableCache: true,  // 开启后,小程序会自动缓存请求结果
  success: (res) => { ... }
})

enableCache是微信小程序基础库提供的特性,会按照HTTP缓存规范自动处理,开发者不需要手动读写Storage。

层级三:离线包与预加载机制

对于一些重要的页面或数据,可以在小程序启动时提前拉取并缓存。

javascript
// app.js
onLaunch() {
  // 提前缓存首页数据
  this.prefetchHomeData()
  
  // 缓存常用配置
  this.prefetchCommonConfig()
},

prefetchHomeData() {
  wx.request({
    url: 'https://api.example.com/home',
    success: (res) => {
      wx.setStorageSync('homeData', res.data)
    }
  })
}

用户打开首页时,如果网络慢,直接读缓存。如果网络快,缓存数据已经被更新了。

离线场景的特殊处理

用户进入电梯后完全没网,这时候怎么处理?

首先,要在请求失败时给出友好提示,而不是白屏或崩溃。

javascript
function fetchData() {
  wx.request({
    url: 'https://api.example.com/list',
    success: (res) => {
      this.setData({ list: res.data })
      wx.setStorageSync('listData', res.data)
    },
    fail: (err) => {
      // 网络请求失败,尝试从缓存读取
      const cached = wx.getStorageSync('listData')
      if (cached) {
        this.setData({ list: cached })
        wx.showToast({ title: '当前为离线数据', icon: 'none' })
      } else {
        wx.showToast({ title: '网络不给力,请稍后重试', icon: 'none' })
      }
    }
  })
}

其次,对于需要提交数据的场景(比如用户填写表单后点击提交),可以先把数据存在本地,等网络恢复后再自动上传。

javascript
function submitForm(data) {
  wx.request({
    url: 'https://api.example.com/submit',
    method: 'POST',
    data: data,
    success: (res) => {
      wx.showToast({ title: '提交成功' })
    },
    fail: () => {
      // 保存到待提交队列
      const queue = wx.getStorageSync('pendingQueue') || []
      queue.push(data)
      wx.setStorageSync('pendingQueue', queue)
      wx.showToast({ title: '已保存,网络恢复后自动提交', icon: 'none' })
    }
  })
}

// 在app.js中监听网络恢复
wx.onNetworkStatusChange((res) => {
  if (res.isConnected) {
    flushPendingQueue()
  }
})

缓存策略的副作用与应对

缓存带来的最大问题是数据不一致。用户看到的是旧数据,可能产生误解。

解决方案是在界面上明确标识数据的新鲜度。

javascript
data: {
  list: [],
  dataSource: 'cache'  // cache 或 network
}

// 在界面上显示
<view class="data-tip" wx:if="{{dataSource === 'cache'}}">
  当前为缓存数据,正在更新...
</view>

另一个问题是缓存占用空间越来越大。虽然小程序会自动清理,但作为负责任的开发者,应该主动管理。

javascript
// 设置缓存过期时间
function setCacheWithExpiry(key, data, ttl = 3600000) {  // 默认1小时
  const item = {
    data: data,
    timestamp: Date.now(),
    ttl: ttl
  }
  wx.setStorageSync(key, item)
}

function getCacheWithExpiry(key) {
  const item = wx.getStorageSync(key)
  if (!item) return null
  
  if (Date.now() - item.timestamp > item.ttl) {
    wx.removeStorageSync(key)
    return null
  }
  return item.data
}

不同数据类型采用不同策略

不是所有数据都需要同样的缓存策略。

静态配置数据:Cache-Control设置较长时间,比如一天。小程序启动时优先读缓存,后台静默更新。

用户个人信息:缓存到Storage,更新频率低,每次用户修改后主动更新缓存。

列表数据:缓存最近3页,设置较短的过期时间(比如5分钟)。用户下拉刷新时强制请求最新数据。

图片资源:使用image组件的lazy-load和本地缓存机制。小程序会自动缓存已加载过的图片。

实时性要求高的数据:比如股票价格、比赛比分、消息通知,不应该读缓存。但可以先用缓存的旧数据占位,等新数据回来后替换。

从设计层面降低网络依赖

技术手段之外,产品设计也能起作用。

首屏内容尽量使用静态数据或本地数据,不要上来就请求三个接口。骨架屏不只是为了美观,更是为了让用户在等待时不至于看到白屏。

对核心流程做离线化设计。比如一个公交查询小程序,可以把全城的线路数据在WiFi环境下预下载到本地。用户离线时仍然可以查线路、算换乘,只是无法获取实时车辆位置。

测试你的离线体验

优化完成后,用微信开发者工具的“网络”面板模拟弱网或离线环境。选择“Slow 3G”看表现,选择“Offline”看提示是否友好。

更真实的测试:把手机调到飞行模式,打开小程序,看看能不能完成核心操作。

一个健康的离线策略,不应该让用户感觉到“断网了”。用户应该只是发现“数据可能不是最新的”,而不是“用不了了”。

电话咨询
QQ咨询
在线咨询
服务投诉