前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >鸿蒙开发实战案例:H5页面资源离线缓存案例

鸿蒙开发实战案例:H5页面资源离线缓存案例

原创
作者头像
小帅聊鸿蒙
发布2025-02-26 20:31:45
发布2025-02-26 20:31:45
920
举报
文章被收录于专栏:鸿蒙开发笔记

介绍

在移动端 H5 应用中实现资源离线缓存是非常重要的,特别是在网络条件不稳定或用户可能在离线状态下使用应用的情况下:

  1. 用户的网络连接不稳定,经常断开,但应用仍需提供可用的功能。
  2. 移动设备在网络覆盖较差的地区,仍然需要访问应用的功能。
  3. 初次加载应用时,将所有资源下载并缓存起来,以后访问时直接从本地加载,提高加载速度。

本模块结合内存缓存和磁盘缓存实现了一个H5页面资源离线缓存案例。

效果图预览

使用说明

  1. 进入本案例页面后,点击可点击下方按钮加载页面。
  2. 第一次进入页面时,页面资源会从网络中加载,加载时会将需要缓存的资源同步保存到内存和磁盘中。
  3. 后续重新进入页面时,因内存和磁盘中已经存在相应资源,会直接从内存/磁盘中读取(可以通过增加版本号方式实现缓存资源更新,需开发者按照自己的业务逻辑来实现),即使在离线状态下也能快速加载页面。

实现思路

  1. 指定需要缓存的资源,h5页面加载时,通过onInterceptRequest回调拦截资源加载请求,将会先检查缓存路径中是否存在对应资源
  2. 若存在对应资源文件,可以自定义缓存处理逻辑,有如下多种处理:
    1. 资源增加版本号,页面加载时优先使用缓存,保证页面快速加载,不影响用户体验,同时通过对比版本号等方法判断资源是否需要更新,如果需要,则发起请求更新缓存资源,后续重新加载页面时使用新的缓存
    2. 默认为稳定资源,直接取出使用(本案例中直接取出使用)
  3. 若不存在,构造http模块发起请求,接收响应后将资源返回给原始请求的同时并保存到本地内存和磁盘中,
代码语言:typescript
复制
Web({ src: this.url, controller: this.controller })
  .javaScriptAccess(true)
  .onInterceptRequest((event) => {
    // 资源请求url
    let url: string = event.request.getRequestUrl();

    // 如果不是http/https请求,走原始逻辑
    if (!url.startsWith('http')) {
      return null;
    }

    // 资源类型:如https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.0/anime.min.js
    // 处理后type值为js
    let type: string;
    type = (url.split('.').pop() as string);
    // url匹配,是否为需要缓存的资源请求
    let matched: boolean = false;
    let cacheableResourceUrls: Array<string> = this.cacheableResourceUrls as Array<string>;
    for (let cacheableResourceUrl of cacheableResourceUrls) {
      if (new RegExp(cacheableResourceUrl, 'g').exec(url)) {
        matched = true;
        break;
      }
    }

    // 开发者可以增加缓存策略,例如:
    // 资源增加版本号,页面加载时优先使用缓存,保证页面快速加载,不影响用户体验,同时通过对比版本号等方法判断资源是否需要更新,如果需要,则发起请求更新缓存资源,后续重新加载页面时使用新的缓存

    if (matched) {
      // 查询缓存
      let cacheResource = (this.offlineResourceManager as OfflineResourceManager).fetchFromCache(url, type);
      // 构造请求响应
      let responseWeb: WebResourceResponse = new WebResourceResponse();
      const promise: Promise<String> = new Promise((resolve: Function, reject: Function) => {
        if (cacheResource) {
          // 返回缓存
          responseWeb.setResponseData(cacheResource as ResponseDataType);
          resolve("success");
        } else {
          // 发起请求
          let httpRequest: http.HttpRequest = http.createHttp();

          httpRequest.request(url, (err: BusinessError, data: http.HttpResponse) => {
            if (data) {
              // 数据正常返回
              (this.offlineResourceManager as OfflineResourceManager).submitToCache(url,
                data.result as ResponseDataType)
              responseWeb.setResponseData(data.result as ResponseDataType);
            } else {
              // 请求出错,返回null
              responseWeb.setResponseData(null);
            }

            responseWeb.setResponseMimeType(MimeType[type]);
            responseWeb.setReasonMessage('OK');
            responseWeb.setResponseCode(200);
            // http响应返回后将promise设置成resolve状态
            resolve("success");
          })
        }
      })
      promise.then(() => {
        responseWeb.setResponseIsReady(true);
      })
      responseWeb.setResponseIsReady(false);
      return responseWeb;
    }

    return null;
  })
DD一下:欢迎大家关注公众号<程序猿百晓生>,可以了解到一下知识点。
代码语言:erlang
复制
1.OpenHarmony开发基础
2.OpenHarmony北向开发环境搭建
3.鸿蒙南向开发环境的搭建
4.鸿蒙生态应用开发白皮书V2.0 & V3.0
5.鸿蒙开发面试真题(含参考答案) 
6.TypeScript入门学习手册
7.OpenHarmony 经典面试题(含参考答案)
8.OpenHarmony设备开发入门【最新版】
9.沉浸式剖析OpenHarmony源代码
10.系统定制指南
11.【OpenHarmony】Uboot 驱动加载流程
12.OpenHarmony构建系统--GN与子系统、部件、模块详解
13.ohos开机init启动流程
14.鸿蒙版性能优化指南
.......

高性能知识点

本案例性能收益

缓存前:耗时2.411s

缓存后:110.120ms

可以看到在使用本地缓存替换后,Web加载耗时明显减少。

工程结构&模块类型

代码语言:shell
复制
h5cache                                             // har类型
|---src/main/ets/pages
|   |---SubWeb.ets                                  // 主页面
|---src/main/ets/common
|   |---DiskCacheManager.ets                        // 磁盘资源缓存管理
|   |---MemoryCacheManager.ets                      // 内存资源缓存管理
|   |---OfflineResourceManager.ets                  // 离线资源缓存管理
|   |---ResponseDataType.ets                        // 响应数据类型
|   |---WebParamsModel.ets                          // Web页面
|---src/main/ets/diskLruCache                       // 手动实现的磁盘缓存
|   |---DiskCacheEntry.ets 
|   |---DiskLruCache.ets   
|   |---FileUtils.ets

模块依赖

本实例依赖common模块来实现日志的打印、资源的调用、依赖动态路由模块来实现页面的动态加载。

写在最后

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:

  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力;
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识;
  • 想要获取更多完整鸿蒙最新学习知识点,可关注B站:码牛课堂;

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
  • 效果图预览
  • 实现思路
    • DD一下:欢迎大家关注公众号<程序猿百晓生>,可以了解到一下知识点。
  • 高性能知识点
  • 工程结构&模块类型
  • 模块依赖
  • 写在最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档