Ionic 7.2 离线存储实现指南

以下是在开源移动端项目中实现 PWA 离线功能(Service Worker + IndexedDB)的完整流程:


一、环境准备
  1. 创建 Ionic 项目

    npm install -g @ionic/cli
    ionic start my-offline-app blank --type=angular
    cd my-offline-app
    

  2. 添加 PWA 支持

    ng add @angular/pwa
    

    自动生成:

    • ngsw-config.json(Service Worker 配置文件)
    • manifest.webmanifest(应用清单)

二、Service Worker 配置

修改 ngsw-config.json 实现资源缓存策略:

{
  "index": "/index.html",
  "assetGroups": [
    {
      "name": "app",
      "installMode": "prefetch",
      "resources": {
        "files": ["/*.css", "/*.js", "/index.html"]
      }
    },
    {
      "name": "assets",
      "installMode": "lazy",
      "updateMode": "prefetch",
      "resources": {
        "files": ["/assets/**"]
      }
    }
  ],
  "dataGroups": [
    {
      "name": "api-cache",
      "urls": ["/api/**"],
      "cacheConfig": {
        "maxSize": 20,
        "maxAge": "1d",
        "strategy": "freshness"
      }
    }
  ]
}


三、IndexedDB 集成
  1. 安装依赖

    npm install idb
    

  2. 创建数据库服务
    src/app/services/db.service.ts

    import { openDB, DBSchema, IDBPDatabase } from 'idb';
    
    interface MyDB extends DBSchema {
      'todos': {
        key: string;
        value: { id: string; text: string; done: boolean };
      };
    }
    
    export class DBService {
      private dbPromise: Promise<IDBPDatabase<MyDB>>;
    
      constructor() {
        this.dbPromise = openDB<MyDB>('my-db', 1, {
          upgrade(db) {
            db.createObjectStore('todos', { keyPath: 'id' });
          }
        });
      }
    
      async addTodo(item: { id: string; text: string; done: boolean }) {
        const db = await this.dbPromise;
        return db.put('todos', item);
      }
    
      async getAllTodos() {
        const db = await this.dbPromise;
        return db.getAll('todos');
      }
    }
    


四、离线同步逻辑

在组件中实现数据同步:

import { Component, OnInit } from '@angular/core';
import { DBService } from './services/db.service';
import { Network } from '@capacitor/network';

@Component({
  selector: 'app-home',
  template: `
    <ion-list>
      <ion-item *ngFor="let todo of todos">
        {{ todo.text }}
      </ion-item>
    </ion-list>
  `
})
export class HomePage implements OnInit {
  todos: any[] = [];

  constructor(private db: DBService) {}

  async ngOnInit() {
    // 加载离线数据
    this.todos = await this.db.getAllTodos();

    // 监听网络状态
    Network.addListener('networkStatusChange', async status => {
      if (status.connected) {
        await this.syncWithServer(); // 同步到服务器
      }
    });
  }

  private async syncWithServer() {
    const pendingItems = await this.db.getAllTodos();
    // 伪代码:发送 POST 请求到后端
    await fetch('/api/sync', { method: 'POST', body: JSON.stringify(pendingItems) });
  }
}


五、关键优化策略
  1. 缓存策略矩阵

    资源类型 策略 更新机制
    核心静态文件 prefetch 版本哈希更新
    图片/媒体 lazy 按需加载
    API 数据 freshness 网络优先,失败用缓存
  2. 离线状态 UI
    app.component.html 添加:

    <div *ngIf="isOffline" class="offline-banner">
      ⚠️ 当前处于离线模式
    </div>
    


六、测试验证
  1. 模拟离线环境

    • Chrome DevTools → Application → Service Worker → 勾选 Offline
    • 触发 IndexedDB 读写操作
  2. 性能指标

    • Lighthouse 审计 PWA 得分 >90
    • 首次加载时间 <3s (3G 网络模拟)

完整示例项目:GitHub 仓库链接(替换为实际开源项目地址)

通过此方案可实现毫秒级本地数据读写,并在网络恢复后自动同步,符合 PWA 的离线优先设计原则。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐