网站职业培训学校江阴网站建设工作室

张小明 2026/1/9 21:10:20
网站职业培训学校,江阴网站建设工作室,如何自己建个人网站,苏州专业网站建设定制流式SSR就是一种渐进式渲染#xff0c;在传统的页面加载流程是#xff1a;请求 → 等待 → 渲染。而渐进式渲染的思路是#xff1a;立即展示缓存的页面快照#xff08;即使是旧内容#xff09;后台请求最新的页面内容无缝替换为最新内容这样用户感知到的加载时间接近于零在传统的页面加载流程是请求 → 等待 → 渲染。而渐进式渲染的思路是立即展示缓存的页面快照即使是旧内容后台请求最新的页面内容无缝替换为最新内容这样用户感知到的加载时间接近于零体验类似于原生 App。前面笔者的文章中提到关于H5页面的快照是客户端做的。本篇文章讲述一种基于 Service Worker 的渐进式渲染方案的原理简单来讲就是将客户端的工作挪到了service worker中。通过给站点开启一个后台运行的service workerservice worker可以独立于webview运行在后台在service worker中劫持包括主文档在内的网络请求对文档内容进行存储并修改返回。技术方案设计整体架构┌─────────────┐ │ 用户访问 │ └──────┬──────┘ │ ▼ ┌─────────────────┐ │ Service Worker │ ◄─── 拦截请求 └────┬────────┬───┘ │ │ │ └─────────┐ ▼ ▼ ┌─────────┐ ┌──────────┐ │ 缓存快照 │ │ 网络请求 │ └────┬────┘ └─────┬────┘ │ │ └────────┬────────┘ ▼ ┌─────────────┐ │ 流式替换 │ └─────────────┘核心代码实现1. HTML 页面注册 Service Worker!DOCTYPE html html langen head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title渐进式渲染示例/title /head body h1Hello World/h1 script data-snapshot (function () { const swEnabled location.search.indexOf(x-swfalse) 0; // 注册 Service Worker swEnabled navigator.serviceWorker navigator.serviceWorker.register(/sw.js) .then(function (registration) { console.log(Service Worker 注册成功:, registration); }) .catch(function (error) { console.log(Service Worker 注册失败:, error); }); // 如果禁用则注销 Service Worker !swEnabled navigator.serviceWorker navigator.serviceWorker.getRegistration(location.href).then((r) { r r.unregister(); }); }()); /script /body /html关键点说明data-snapshot属性标记这是快照阶段需要保留的脚本支持通过?x-swfalse参数禁用 Service Worker禁用时会自动注销已注册的 Service Worker2. Service Worker 核心逻辑// sw.js self.addEventListener(fetch, (event) { // 只拦截主文档请求 if (event.request.destination ! document) { return; } // 支持禁用功能 if (event.request.url.indexOf(x-swfalse) 0) { event.waitUntil(caches.delete(my-cache)); return; } event.respondWith(handleFetch(event.request)); }); self.addEventListener(install, (event) { console.log(Service Worker 安装); self.skipWaiting(); // 立即激活 });3. 脚本过滤策略function replaceScripts(text, regularStream) { return text.replace(/script\b[^]*(?:(?!\/script)[^]*)*\/script/gi, (match) { // 快照阶段只保留 data-snapshot 脚本 // 正式阶段只保留普通脚本 if (match.indexOf(data-snapshot) 0) { return regularStream ? : match; } return regularStream ? match : ; }); }为什么要过滤脚本快照阶段避免执行业务逻辑脚本可能依赖未加载的资源正式阶段避免重复执行初始化脚本4. 流式渲染核心function withSnapshot(snapshot, request) { return new Response(new ReadableStream({ start(controller) { const encoder new TextEncoder(); const decoder new TextDecoder(); // 第一步立即输出快照 controller.enqueue(encoder.encode(snapshot)); let firstStream true; // 第二步请求最新内容 fetchAndStore(request).then((response) { const reader response.body.getReader(); function push() { reader.read().then(({ done, value }) { if (done) { controller.close(); return; } if (firstStream) { firstStream false; // 第三步清空页面 controller.enqueue(encoder.encode( scriptdocument.head.innerHTML ;document.body.innerHTML ;/script )); // 第四步注入最新内容 const text decoder.decode(value); const head text.match(/head([\s\S]*?)\/head/i); const body text.match(/body([\s\S]*?)\/body/i); if (head body) { controller.enqueue(encoder.encode( scriptdocument.head.innerHTML ${head[1].trim().replace(/\n/g, )}/script )); controller.enqueue(encoder.encode(replaceScripts(body[1], true))); } } else { controller.enqueue(value); } push(); }); } push(); }); }, })); }为什么要清空 DOM快照内容和最新内容可能结构不同直接追加会导致内容重复清空后重新注入确保页面状态一致为什么用 innerHTML 注入流式响应中我们无法直接操作 DOM只能通过推送script标签让浏览器执行 JavaScriptinnerHTML是最简单的 DOM 替换方式5. 缓存管理Service Worker 的缓存存储在 Cache Storage API 中这是浏览器提供的专门用于 Service Worker 的持久化存储空间。实际上不需要关心物理位置因为浏览器完全管理这些文件。function fetchAndStore(request) { return fetch(request) .then((networkResponse) { if (networkResponse.ok) { // 克隆响应用于缓存 const cacheResponse networkResponse.clone(); caches.open(my-cache).then((cache) { cache.put(request, cacheResponse); }); } return networkResponse; }); } function handleFetch(request) { return caches.match(request) .then((response) { if (response) { // 有缓存先展示快照再更新 return readResponseText(response).then((snapshot) { return withSnapshot(snapshot, request); }); } // 无缓存直接请求 return fetchAndStore(request); }); }为什么要 clone 响应Response 对象的 body 只能读取一次流的特性需要一份给缓存一份给浏览器clone()创建独立的副本工作流程详解首次访问无缓存用户访问 → Service Worker 拦截 → 无缓存 → 网络请求 → 返回内容 → 存入缓存二次访问有缓存用户访问 ↓ Service Worker 拦截 ↓ 读取缓存快照去除普通脚本 ↓ 立即返回快照内容 ← 用户看到页面 ↓ 后台发起网络请求 ↓ 清空 DOM ↓ 注入最新 head 和 body ↓ 更新缓存注意事项上述只讲述了该方案的基本原理实际应用要考虑更多的因素如App 环境兼容性、缓存策略、基础设施依赖等下面是方案对比维度客户端方案Service Worker 方案首次访问拦截✅ 可以拦截❌ 无法拦截跨平台能力❌ 需要各端适配✅ Web 标准通用更新速度⚠️ 需要发版✅ 实时生效开发成本⚠️ 需要端上开发⚠️ 需要 Web 开发维护成本❌ 多端维护✅ 单一维护灵活性⚠️ 受限于客户端版本✅ 完全可控降级能力⚠️ 需要发版回滚✅ 秒级降级总结如果你的业务是纯 Web 应用PWA) → Service Worker 是最佳选择如果你的业务在 App 内 → 优先考虑客户端方案
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

公司的网站制作wordpress怎么设置只显示摘要

你是否曾因显卡驱动问题而陷入困境?当系统频繁蓝屏、游戏帧率骤降或新驱动安装失败时,你是否感到束手无策?这些困扰无数用户的难题,正是Display Driver Uninstaller(DDU)专业驱动清理工具所要解决的核心问题…

张小明 2025/12/25 7:36:44 网站建设

网站制作公司网站源码iis网站属性里

如何通过 GitHub 镜像快速部署 HunyuanVideo-Foley 实现视频自动配乐 在短视频日活突破十亿、内容生产节奏以“分钟”为单位的今天,音效设计却依然是许多团队卡脖子的环节。一个5分钟的创意短片,可能拍摄只要两小时,剪辑一晚上搞定&#xff0…

张小明 2025/12/27 18:51:56 网站建设

中国网站设计模板下载个人主页链接怎么填写

第一章:Open-AutoGLM邀请码真实发放机制Open-AutoGLM 作为新一代开源大语言模型协作平台,其访问权限通过邀请码机制进行控制。该机制旨在保障社区质量,同时防止自动化脚本批量注册带来的安全风险。邀请码的发放并非公开申请,而是基…

张小明 2026/1/9 14:51:37 网站建设

网站上传的流程中国有名的网站建设公司

浏览器的进程模型何为进程?程序运行需要有它自己专属的内存空间,可以把这块内存空间简单理解为进程每个应用至少有一个进程,进程之间相互独立,即使要通信,也需要双方同意。何为线程?有了进程后,…

张小明 2025/12/26 14:40:05 网站建设

谷歌网站收录入口ppt 如何做网站交互式

5分钟掌握小说下载神器:构建终身免费的数字图书馆 【免费下载链接】novel-downloader 一个可扩展的通用型小说下载器。 项目地址: https://gitcode.com/gh_mirrors/no/novel-downloader 在信息爆炸的数字时代,你是否曾因心爱的小说网站突然关闭而…

张小明 2026/1/6 4:16:49 网站建设