当前位置: 首页 > news >正文

企业H5站点升级PWA (二)

下面直接给一套在你现有结构上最小侵入地接入 Service Worker 的方案,做到:

  • 保留你现在的导航和动态 fetch 子页逻辑;
  • 只缓存静态资源(HTML/JS/CSS/图片),不拦截你的业务 API;
  • 支持基本的 PWA:可安装、离线时至少能打开壳页面。

分三步:


1. 新增 sw.js(Service Worker)

放在和 index.html 同级的 wwwroot 目录:

const CACHE_NAME = 'app-static-v1';// 这里列出首要静态资源(至少把当前壳和主 JS/CSS 缓存起来)
const PRECACHE_URLS = ['./','./index.html','./index.css','./index.js','./homeConfig.js','./pda.js','./auth.js','./bootstrap.bundle.min.js', './manifest.json'
];// 安装阶段:预缓存核心静态资源
self.addEventListener('install', (event) => {event.waitUntil(caches.open(CACHE_NAME).then((cache) => {return cache.addAll(PRECACHE_URLS);}));// 跳过等待,立即进入 activateself.skipWaiting();
});// 激活阶段:清理旧版本缓存
self.addEventListener('activate', (event) => {event.waitUntil(caches.keys().then((keys) => {return Promise.all(keys.map((key) => {if (key !== CACHE_NAME) {return caches.delete(key);}return null;}));}));self.clients.claim();
});// 请求拦截:对静态资源使用 cache-first,对 API / 动态接口放行
self.addEventListener('fetch', (event) => {const { request } = event;// 只处理 GETif (request.method !== 'GET') {return;}const url = new URL(request.url);// 1. 避免干扰 API(根据你的 API_BASE 和常见前缀排除)//    如果你 API 跑在同域 /api 下,可以按需修改if (url.pathname.startsWith('/api/')|| url.pathname.startsWith('/swagger')|| url.pathname.includes('/signalr')) {return;}// 2. 对 HTML/CSS/JS/图片等静态资源做 cache-first//    这里用简单的策略:先查缓存,没命中再走网络并回填event.respondWith(caches.match(request).then((cached) => {if (cached) {return cached;}return fetch(request).then((response) => {// 只缓存 200 的基础静态资源if (!response || response.status !== 200 || response.type === 'opaque') {return response;}const clone = response.clone();caches.open(CACHE_NAME).then((cache) => {cache.put(request, clone);});return response;}).catch(() => {// 离线兜底:请求 HTML 时,回退到首页if (request.headers.get('accept')?.includes('text/html')) {return caches.match('./index.html');}return new Response('网络不可用,且本资源未被缓存。', {status: 503,headers: { 'Content-Type': 'text/plain; charset=utf-8' }});});}));
});

要点:

  • 只对静态资源起作用,不会挡住你 fetch(url) 去拉 pda.html / add.html 等页面(这些也是静态文件,能自动享受缓存)。
  • 避免拦 API:简单按路径前缀排除,你可以根据实际 API 路径调整。

2. 在 index.html 注册 Service Worker

在你已有的 index.html 里(</body> 前)加一段注册逻辑。你当前文件尾部大致是:

    <div class="footer hide" id="footer"><button type="button" data-url="home" onclick="navigateTo(this)">首页</button><button type="button" onclick="alert('我的')">我的</button></div><script src="bootstrap.bundle.min.js"></script><script src="index.js"></script>
</body>
</html>

改为(新增一段 serviceWorker 注册脚本):

    <div class="footer hide" id="footer"><button type="button" data-url="home" onclick="navigateTo(this)">首页</button><button type="button" onclick="alert('我的')">我的</button></div><script src="bootstrap.bundle.min.js"></script><script src="index.js"></script><script>if ('serviceWorker' in navigator) {window.addEventListener('load', function () {navigator.serviceWorker.register('./sw.js').then(function (registration) {console.log('Service Worker 注册成功:', registration.scope);}).catch(function (error) {console.error('Service Worker 注册失败:', error);});});}</script>
</body>
</html>

不动你现有逻辑,只是在页面加载后注册 sw.js


3. 确认 manifest.json 和 HTTPS

index.html 已经有:

<link rel="manifest" href="manifest.json">

检查两点即可:

  1. manifest.json 至少要包含:
{"name": "App","short_name": "MyApp","start_url": "./","display": "standalone","background_color": "#ffffff","theme_color": "#000000","icons": [{"src": "densen26.jpg","sizes": "192x192","type": "image/jpeg"}]
}
  1. PWA 要求:
    • 浏览器访问时必须是 HTTPS 或 http://localhost
    • 如果你是 WinForms + WebView2 本地文件加载,Service Worker 默认是不工作的,需要:
      • 改为在本地起一个 http://127.0.0.1:xxxx 小服务器托管 wwwroot
      • WebView2 加载这个本地 http 地址。

4. 和你现有 index.js 的配合关系

这套改造对你当前代码完全透明:

  • loadPagefetch(url)
    • 第一次仍然从网络拉 pda.html / add.html
    • 被 Service Worker 和浏览器缓存后,再次访问会命中缓存,体验更快。
  • 动态加载的 homeConfig.js / pda.js 等脚本,只要它们的 URL 在缓存策略覆盖范围内,也会被缓存。
  • 你自己的 reload() / initpda() / renderHomeButtons() 完全不需要改。

如果后面你想升级策略,比如:

  • 首次打开时就预缓存 pda.htmladd.html 等子页面;
  • 对某些资源用 stale-while-revalidate 策略;

只需要再调整 PRECACHE_URLSfetch 里的逻辑即可。


http://www.jsqmd.com/news/392360/

相关文章:

  • OpenClaw(原Clawdbot)2026部署教程:阿里云快速搭建指南
  • OpenClaw(原Clawdbot)2026部署教程:阿里云轻松搞定秘籍
  • 美团三面:8000万订单查不动,一定要分库分表吗?
  • 美团三面:千万级订单架构,如何设计一套“永不跳变”的状态流转体系?
  • [raspberry pi4]拿到raspberry pi4(Raspbian GNU/Linux 11 (bullseye))之后,如何熟悉单板-3
  • 线缆外皮破损检测:保障电气安全的 7 个核心策略,附 OpenCV+Halcon 实战代码! - 指南
  • [raspberry pi4]拿到raspberry pi4之后,如何熟悉单板-2
  • 微信红包:为什么每次只有你抢 0.01?不是手气差,是算法在“杀熟”?
  • 微信小程序springboot茶叶园文化交流设计
  • [算法]树形dp
  • HDFS 与 HBase 的协同工作:实时大数据存储方案
  • 大数据领域的环保科技数据监测
  • 探索大数据领域HBase的安全漏洞与防范措施
  • 2.18学习
  • 实用指南:学习Three.js--缓冲类型几何体(BufferGeometry)
  • 巴菲特的科技股投资转变:与时俱进的智慧
  • 如何获取26T快客空间,揭秘夸克26T扩容底层逻辑
  • glm-ocr ollama使用 python
  • 屏幕元素定位(Grounding) ollama两个模型
  • 新兴市场vs发达市场:股市估值比较
  • 并行编程实战——CUDA编程的内存建
  • Docker Registry私有仓库搭建与使用
  • 京东e卡回收新风口,闲置卡券如何秒变现金? - 京顺回收
  • 单片机嵌入式试题(第33期)你真理解 volatile 了?:嵌入式工程师必懂的底层原理
  • 退役划水二:一些音乐有关的东西
  • DeepSeek+LangGraph构建企业级多模态RAG:从PDF繁琐解析到Agentic智能检索全流程实战
  • 抗饱和处理
  • 完整教程:【Docker入门】Docker原理和安装
  • [SpringBoot]@SpringBootTest标签作用
  • 近日总结以及后续408规划