[{"data":1,"prerenderedAt":990},["ShallowReactive",2],{"navigation_docs":3,"-web-dev-browser-service-worker-request-flow":352,"-web-dev-browser-service-worker-request-flow-surround":985},[4,54,83,116,125,161,179,200],{"title":5,"path":6,"stem":7,"children":8},"Ai","/ai","ai",[9,12,42,46,50],{"title":10,"path":6,"stem":11},"AI 技術探索","ai/index",{"title":13,"path":14,"stem":15,"children":16,"page":41},"Rag","/ai/rag","ai/RAG",[17,21,25,29,33,37],{"title":18,"path":19,"stem":20},"BM25 演算法深入解析：從 TF-IDF 到現代搜尋引擎的核心技術","/ai/rag/bm25-deep-dive-from-tf-idf-to-rag","ai/RAG/bm25-deep-dive-from-tf-idf-to-rag",{"title":22,"path":23,"stem":24},"Dense Retrieval（向量檢索）深入解析","/ai/rag/dense-retrieval-deep-dive","ai/RAG/dense-retrieval-deep-dive",{"title":26,"path":27,"stem":28},"RAG（Retrieval-Augmented Generation）原理與實作入門","/ai/rag/rag-intro-principles-and-implementation","ai/RAG/rag-intro-principles-and-implementation",{"title":30,"path":31,"stem":32},"RAG Retrieval Strategy 深入解析","/ai/rag/rag-retrieval-strategy-deep-dive","ai/RAG/rag-retrieval-strategy-deep-dive",{"title":34,"path":35,"stem":36},"Reciprocal Rank Fusion（RRF）教學：打造更穩定的檢索融合策略","/ai/rag/rrf-reciprocal-rank-fusion-guide","ai/RAG/rrf-reciprocal-rank-fusion-guide",{"title":38,"path":39,"stem":40},"TF-IDF（Term Frequency–Inverse Document Frequency）深入解析","/ai/rag/tf-idf-deep-dive","ai/RAG/tf-idf-deep-dive",false,{"title":43,"path":44,"stem":45},"Docus AI 功能完整實作指南","/ai/docus-ai-implementation","ai/docus-ai-implementation",{"title":47,"path":48,"stem":49},"llms.txt 是什麼？在 Nuxt 中控制 AI 與搜尋引擎爬蟲的新方式","/ai/llms-txt","ai/llms-txt",{"title":51,"path":52,"stem":53},"MCP（Model Context Protocol）是什麼？用「AI 的 USB-C」理解模型如何安全連接工具與資料","/ai/mcp_concept","ai/mcp_concept",{"title":55,"path":56,"stem":57,"children":58,"page":41},"Data Analysis","/data-analysis","data-analysis",[59,63,67,71,75,79],{"title":60,"path":61,"stem":62},"Exploratory Data Analysis（EDA）資料探索分析入門","/data-analysis/exploratory-data-analysis-eda","data-analysis/exploratory-data-analysis-eda",{"title":64,"path":65,"stem":66},"PR-AUC 深入解析：不平衡分類問題的重要評估指標","/data-analysis/pr-auc-for-imbalanced-classification","data-analysis/pr-auc-for-imbalanced-classification",{"title":68,"path":69,"stem":70},"ROC-AUC 深入解析：理解分類模型的判斷能力","/data-analysis/roc-auc-complete-guide","data-analysis/roc-auc-complete-guide",{"title":72,"path":73,"stem":74},"SHAP（SHapley Additive exPlanations）模型解釋方法深入解析","/data-analysis/shap-model-interpretation-complete-guide","data-analysis/shap-model-interpretation-complete-guide",{"title":76,"path":77,"stem":78},"Social Network Analysis（SNA）深入解析","/data-analysis/social-network-analysis-sna","data-analysis/social-network-analysis-sna",{"title":80,"path":81,"stem":82},"Time-based Split：為什麼時間序列資料不能使用 Random Split？","/data-analysis/time-based-split-vs-random-split","data-analysis/time-based-split-vs-random-split",{"title":84,"path":85,"stem":86,"children":87,"page":41},"MachineLearning","/machine_learning","machine_learning",[88,92,96,100,104,108,112],{"title":89,"path":90,"stem":91},"Confusion Matrix（混淆矩陣）完整解析","/machine_learning/confusion-matrix","machine_learning/confusion-matrix",{"title":93,"path":94,"stem":95},"Decision Tree 模型完整教學：從原理到 Python 實作","/machine_learning/decision-tree-complete-guide","machine_learning/decision-tree-complete-guide",{"title":97,"path":98,"stem":99},"為什麼 Decision Tree 在 Tabular Data 上常常勝過 Deep Learning？","/machine_learning/decision-tree-vs-deep-learning-on-tabular-data","machine_learning/decision-tree-vs-deep-learning-on-tabular-data",{"title":101,"path":102,"stem":103},"LightGBM 模型入門：理解高效能的 Gradient Boosting 演算法","/machine_learning/lightgbm-intro-for-tabular-data","machine_learning/lightgbm-intro-for-tabular-data",{"title":105,"path":106,"stem":107},"Logistic Regression（Logit 回歸）完整教學","/machine_learning/logistic-regression-complete-guide","machine_learning/logistic-regression-complete-guide",{"title":109,"path":110,"stem":111},"為什麼模型訓練需要 Train / Validation / Test Dataset？","/machine_learning/train-validation-test-dataset","machine_learning/train-validation-test-dataset",{"title":113,"path":114,"stem":115},"XGBoost 原理與實務教學","/machine_learning/xgboost-complete-guide","machine_learning/xgboost-complete-guide",{"title":117,"path":118,"stem":119,"children":120,"page":41},"Network","/network","network",[121],{"title":122,"path":123,"stem":124},"DNS 設定入門：CNAME vs A Record 完整解析","/network/dns-cname-vs-a-record-guide","network/dns-cname-vs-a-record-guide",{"title":126,"path":127,"stem":128,"children":129},"Nuxt","/nuxt","nuxt",[130,133,137,141,145,149,153,157],{"title":131,"path":127,"stem":132},"Nuxt 實戰指南","nuxt/index",{"title":134,"path":135,"stem":136},"Abstraction Layer 與 Adapter 的差別，一次搞懂設計角色","/nuxt/adapter_abstraction_layer","nuxt/adapter_abstraction_layer",{"title":138,"path":139,"stem":140},"Nuxt 4 全面理解 — 專案檔案結構解析","/nuxt/directory_structure","nuxt/directory_structure",{"title":142,"path":143,"stem":144},"Nuxt 前端 build 流程完整解析","/nuxt/frontend_build","nuxt/frontend_build",{"title":146,"path":147,"stem":148},"Nitro 是什麼？從 Nuxt 專案到 Server 與 Edge 的關鍵引擎","/nuxt/nitro","nuxt/nitro",{"title":150,"path":151,"stem":152},"深入理解 Nuxt 的 .nuxt 與 .output：為什麼部署時一定要分清楚？","/nuxt/nuxt_and_output","nuxt/nuxt_and_output",{"title":154,"path":155,"stem":156},"Nuxt 中 dev、build、preview 的差異一次搞懂","/nuxt/nuxt_dev_build_preview","nuxt/nuxt_dev_build_preview",{"title":158,"path":159,"stem":160},"Nuxt Image vs \u003Cimg>：為什麼 Nuxt 3 專案幾乎都該用 \u003CNuxtImg>？","/nuxt/nuxt_image","nuxt/nuxt_image",{"title":162,"path":163,"stem":164,"children":165},"Python 程式開發","/python","python/index",[166,167,171,175],{"title":162,"path":163,"stem":164},{"title":168,"path":169,"stem":170},"如何在 FastAPI 中調用記憶體 Buffer 回傳圖片 (附實例)","/python/memory_buffer","python/memory_buffer",{"title":172,"path":173,"stem":174},"Python 單元測試教學：如何為你的程式撰寫 Test","/python/python-unit-testing-unittest-pytest","python/python-unit-testing-unittest-pytest",{"title":176,"path":177,"stem":178},"如何使用 uv 取代 pip：改善 Python 專案的開發流程","/python/uv","python/uv",{"title":180,"path":181,"stem":182,"children":183,"page":41},"Statistic","/statistic","statistic",[184,188,192,196],{"title":185,"path":186,"stem":187},"卡方檢定（Chi-Square Test）入門教學","/statistic/chi-square-test-intro","statistic/chi-square-test-intro",{"title":189,"path":190,"stem":191},"常見抽樣方法（Sampling Methods）教學：Stratified、Quota、Convenience、Systematic、Simple Random","/statistic/common-sampling-methods-guide","statistic/common-sampling-methods-guide",{"title":193,"path":194,"stem":195},"Cramér’s V 指標介紹：如何衡量兩個類別變數之間的關聯","/statistic/cramers-v-for-categorical-association","statistic/cramers-v-for-categorical-association",{"title":197,"path":198,"stem":199},"Mann–Whitney U 與 Kolmogorov–Smirnov（KS）檢定：非參數統計檢定的入門指南","/statistic/mann-whitney-u-and-ks-test-intro","statistic/mann-whitney-u-and-ks-test-intro",{"title":201,"path":202,"stem":203,"children":204},"WebDev","/web_dev","web_dev",[205,208,234,248,282,312,334],{"title":206,"path":202,"stem":207},"Web 前端開發","web_dev/index",{"title":209,"path":210,"stem":211,"children":212},"瀏覽器與渲染","/web_dev/browser","web_dev/browser/index",[213,214,218,222,226,230],{"title":209,"path":210,"stem":211},{"title":215,"path":216,"stem":217},"瀏覽器儲存空間完整解析：Cookie、localStorage、IndexedDB 到 Cache Storage","/web_dev/browser/browser-storage-comprehensive-guide","web_dev/browser/browser-storage-comprehensive-guide",{"title":219,"path":220,"stem":221},"DOM (Document Object Model) 深入解析","/web_dev/browser/dom","web_dev/browser/dom",{"title":223,"path":224,"stem":225},"Service Worker Request Flow 深入解析","/web_dev/browser/service-worker-request-flow","web_dev/browser/service-worker-request-flow",{"title":227,"path":228,"stem":229},"CSR、SSR 與 SSG 是什麼？前端渲染策略完整比較","/web_dev/browser/ssr_csr_ssg","web_dev/browser/ssr_csr_ssg",{"title":231,"path":232,"stem":233},"Virtual DOM 深入解析：為什麼它能優化前端效能？","/web_dev/browser/virtual_dom","web_dev/browser/virtual_dom",{"title":235,"path":236,"stem":237,"children":238},"圖形技術","/web_dev/graphics","web_dev/graphics/index",[239,240,244],{"title":235,"path":236,"stem":237},{"title":241,"path":242,"stem":243},"為什麼 Three.js 專案幾乎都選擇 CSR？從 SSR 問題談起","/web_dev/graphics/threejs_csr","web_dev/graphics/threejs_csr",{"title":245,"path":246,"stem":247},"WebGL 是什麼？為什麼前端 3D 幾乎都靠它？","/web_dev/graphics/webgl","web_dev/graphics/webGL",{"title":249,"path":250,"stem":251,"children":252},"架構與配置","/web_dev/infrastructure","web_dev/infrastructure/index",[253,254,258,262,266,270,274,278],{"title":249,"path":250,"stem":251},{"title":255,"path":256,"stem":257},"Zeabur + K3s + Nuxt 部署架構完整解析","/web_dev/infrastructure/k3s-zeabur","web_dev/infrastructure/K3s-zeabur",{"title":259,"path":260,"stem":261},"ECS vs Docker vs Kubernetes：從部署堆疊理解三層架構","/web_dev/infrastructure/ecs-docker-kubernetes-stack","web_dev/infrastructure/ecs-docker-kubernetes-stack",{"title":263,"path":264,"stem":265},"ECS vs VPS 是什麼？從部署網站的角度一次搞懂差別","/web_dev/infrastructure/ecs-vs-vps","web_dev/infrastructure/ecs-vs-vps",{"title":267,"path":268,"stem":269},"Zeabur 內網服務連線完整入門指南","/web_dev/infrastructure/k3s-internal-networking","web_dev/infrastructure/k3s-internal-networking",{"title":271,"path":272,"stem":273},"使用 Microservices 架構設計系統的優勢解析","/web_dev/infrastructure/microservices-architecture-advantages","web_dev/infrastructure/microservices-architecture-advantages",{"title":275,"path":276,"stem":277},"Nginx 入門教學：從反向代理到與 Kubernetes 的架構比較","/web_dev/infrastructure/nginx-intro","web_dev/infrastructure/nginx-intro",{"title":279,"path":280,"stem":281},"YAML 配置是什麼？為什麼現代開發都在用它","/web_dev/infrastructure/yaml-configuration","web_dev/infrastructure/yaml-configuration",{"title":283,"path":284,"stem":285,"children":286},"網絡與通訊","/web_dev/network","web_dev/network/index",[287,288,292,296,300,304,308],{"title":283,"path":284,"stem":285},{"title":289,"path":290,"stem":291},"HTTP Request 結構完整解析：從 Request Line 到 Header 一次看懂","/web_dev/network/http-request-structure","web_dev/network/http-request-structure",{"title":293,"path":294,"stem":295},"OSI 模型（Open Systems Interconnection Model）完整解析","/web_dev/network/osi-model","web_dev/network/osi-model",{"title":297,"path":298,"stem":299},"RESTful API 設計原則與實務解析","/web_dev/network/restful-api","web_dev/network/restful-api",{"title":301,"path":302,"stem":303},"RESTful API 五大設計原則深入解析","/web_dev/network/restful-api-principles","web_dev/network/restful-api-principles",{"title":305,"path":306,"stem":307},"Server-Sent Events (SSE) 深入解析與實作教學","/web_dev/network/sse-introduction","web_dev/network/sse-introduction",{"title":309,"path":310,"stem":311},"WebSocket 入門教學：從概念到 Node.js 實作","/web_dev/network/websocket-introduction","web_dev/network/websocket-introduction",{"title":313,"path":314,"stem":315,"children":316},"認證與安全","/web_dev/security","web_dev/security/index",[317,318,322,326,330],{"title":313,"path":314,"stem":315},{"title":319,"path":320,"stem":321},"使用 Cookie 與 Session 建立使用者驗證（完整新手教學）","/web_dev/security/cookie-session-authentication","web_dev/security/cookie-session-authentication",{"title":323,"path":324,"stem":325},"JWT 驗證機制完整解析：從登入流程到實務應用","/web_dev/security/jwt-authentication","web_dev/security/jwt-authentication",{"title":327,"path":328,"stem":329},"Secret Key 簽名是什麼？從零理解資料簽名的本質","/web_dev/security/secret-key-signing","web_dev/security/secret-key-signing",{"title":331,"path":332,"stem":333},"SSH（Secure Shell）是什麼？從遠端登入到安全通道的核心概念","/web_dev/security/ssh","web_dev/security/ssh",{"title":335,"path":336,"stem":337,"children":338},"SEO 與規範","/web_dev/seo","web_dev/seo/index",[339,340,344,348],{"title":335,"path":336,"stem":337},{"title":341,"path":342,"stem":343},"Canonical URL 是什麼？用生活化方式搞懂前端 SEO 的基本保命符","/web_dev/seo/canonical_link","web_dev/seo/canonical_link",{"title":345,"path":346,"stem":347},"robots.txt 是什麼？SEO 的第一道守門員","/web_dev/seo/robot_txt","web_dev/seo/robot_txt",{"title":349,"path":350,"stem":351},"Nuxt SEO 中的 Meta 與 SEO 工具是如何運作的？","/web_dev/seo/seo","web_dev/seo/seo",{"id":353,"title":223,"body":354,"description":972,"extension":973,"links":974,"meta":975,"navigation":982,"path":224,"seo":983,"stem":225,"__hash__":984},"docs/web_dev/browser/service-worker-request-flow.md",{"type":355,"value":356,"toc":956},"minimark",[357,361,374,377,380,385,388,396,403,406,416,418,422,425,431,433,437,443,448,455,459,462,529,533,540,545,556,560,566,568,572,575,579,601,672,676,692,754,758,775,926,928,931,938,940,943,949,952],[358,359,223],"h1",{"id":360},"service-worker-request-flow-深入解析",[362,363,364,365,369,370,373],"p",{},"在現代 Web 開發中，只要談到 ",[366,367,368],"strong",{},"PWA（Progressive Web App）","，幾乎一定會提到 ",[366,371,372],{},"Service Worker (SW)","。但很多人對它的理解停留在「可以離線使用」這句話，卻不清楚它真正的 Request Flow 到底是怎麼運作的。",[362,375,376],{},"這篇文章會用「流程圖 + 實際情境 + 實作策略」帶你理解 Service Worker 的請求生命週期。只要理解這一篇，你就會真正掌握 SW 的核心機制。",[378,379],"hr",{},[381,382,384],"h2",{"id":383},"service-worker-在瀏覽器中的位置","Service Worker 在瀏覽器中的位置",[362,386,387],{},"在介紹流程之前，我們先釐清一件重要的事情：",[389,390,391],"blockquote",{},[362,392,393],{},[366,394,395],{},"Service Worker 不是伺服器，而是瀏覽器裡的一層「攔截代理」。",[362,397,398,399],{},"當使用者打開網站時，請求流程其實會變成：\n",[400,401,402],"code",{},"Page → Service Worker → (Cache 或 Server)",[362,404,405],{},"它就像是瀏覽器內建的一個 Proxy，可以在 Request 送到 Server 之前先攔截並決定怎麼處理。它的架構位置如下：",[407,408,414],"pre",{"className":409,"code":411,"language":412,"meta":413},[410],"language-text","Browser Page\n    │\n    ▼\nService Worker\n    │\n┌───┴────────────┐\n│                │\nCache API     Fetch API\n│                │\n▼                ▼\nCache          Server\n","text","",[400,415,411],{"__ignoreMap":413},[378,417],{},[381,419,421],{"id":420},"整體-request-flow-圖解","整體 Request Flow 圖解",[362,423,424],{},"當使用者開啟網站時，核心工作流程如下：",[407,426,429],{"className":427,"code":428,"language":412,"meta":413},[410],"使用者開啟網頁\n      ↓\nBrowser Page\n      ↓\nHTTP request\n      ↓\nService Worker（攔截）\n      ↓\n┌───────────────┬───────────────┐\n│  Cache 有資料  │  Cache 沒資料  │\n│  (cache hit)  │  (cache miss) │\n└───────┬───────┴───────┬───────┘\n        ↓               ↓\n    回傳 cache    向 server 發 request\n        ↓               ↓\n    Page 收到資料    Server 回應\n                        ↓\n                     回傳 Page\n                        ↓\n                  （可選）寫入 cache\n",[400,430,428],{"__ignoreMap":413},[378,432],{},[381,434,436],{"id":435},"實際情境載入-indexhtml","實際情境：載入 index.html",[362,438,439,440],{},"假設你打開：",[400,441,442],{},"https://mysite.com",[444,445,447],"h3",{"id":446},"step-1page-發出-request","Step 1：Page 發出 request",[362,449,450,451,454],{},"瀏覽器發出請求：",[400,452,453],{},"GET /index.html","。如果沒有 SW，請求會直接送往 Server。",[444,456,458],{"id":457},"step-2service-worker-攔截請求","Step 2：Service Worker 攔截請求",[362,460,461],{},"只要 SW 已經註冊並啟用，所有請求都會先進到 SW。",[407,463,467],{"className":464,"code":465,"language":466,"meta":413,"style":413},"language-js shiki shiki-themes github-dark","self.addEventListener(\"fetch\", (event) => {\n  console.log(\"intercepted:\", event.request.url)\n})\n","js",[400,468,469,506,523],{"__ignoreMap":413},[470,471,474,478,482,485,489,492,496,499,503],"span",{"class":472,"line":473},"line",1,[470,475,477],{"class":476},"s95oV","self.",[470,479,481],{"class":480},"svObZ","addEventListener",[470,483,484],{"class":476},"(",[470,486,488],{"class":487},"sU2Wk","\"fetch\"",[470,490,491],{"class":476},", (",[470,493,495],{"class":494},"s9osk","event",[470,497,498],{"class":476},") ",[470,500,502],{"class":501},"snl16","=>",[470,504,505],{"class":476}," {\n",[470,507,509,512,515,517,520],{"class":472,"line":508},2,[470,510,511],{"class":476},"  console.",[470,513,514],{"class":480},"log",[470,516,484],{"class":476},[470,518,519],{"class":487},"\"intercepted:\"",[470,521,522],{"class":476},", event.request.url)\n",[470,524,526],{"class":472,"line":525},3,[470,527,528],{"class":476},"})\n",[444,530,532],{"id":531},"step-3檢查-cache","Step 3：檢查 Cache",[362,534,535,536,539],{},"SW 會決定如何回應，通常會檢查 ",[400,537,538],{},"caches.match(event.request)","。",[541,542,544],"h4",{"id":543},"情況一cache-hit有快取","情況一：Cache Hit（有快取）",[362,546,547,548,551,552,555],{},"流程：",[400,549,550],{},"Page → SW → Cache → Page","\n結果：不需要網路、回應極快、支援離線。這就是 ",[366,553,554],{},"Offline-first"," 行為。",[541,557,559],{"id":558},"情況二cache-miss沒有快取","情況二：Cache Miss（沒有快取）",[362,561,547,562,565],{},[400,563,564],{},"Page → SW → Server → SW → Page","\n這時 SW 就像透明代理一樣，將請求轉發給 Server。",[378,567],{},[381,569,571],{"id":570},"真正關鍵快取策略caching-strategy","真正關鍵：快取策略（Caching Strategy）",[362,573,574],{},"Service Worker 的 Request Flow 取決於你使用的策略。以下是實務上最常見的三種模式：",[444,576,578],{"id":577},"_1-cache-first離線優先","1. Cache First（離線優先）",[580,581,582,589,595],"ul",{},[583,584,585,588],"li",{},[366,586,587],{},"流程","：Page ↓ SW ↓ Cache? → (Yes: 回傳) / (No: Server → Cache → Page)",[583,590,591,594],{},[366,592,593],{},"適合","：靜態資源、投影片、教學網站、SPA build 後的 assets。",[583,596,597,600],{},[366,598,599],{},"實作","：",[407,602,604],{"className":464,"code":603,"language":466,"meta":413,"style":413},"event.respondWith(\n  caches.match(event.request).then((res) => {\n    return res || fetch(event.request)\n  })\n)\n",[400,605,606,617,643,660,666],{"__ignoreMap":413},[470,607,608,611,614],{"class":472,"line":473},[470,609,610],{"class":476},"event.",[470,612,613],{"class":480},"respondWith",[470,615,616],{"class":476},"(\n",[470,618,619,622,625,628,631,634,637,639,641],{"class":472,"line":508},[470,620,621],{"class":476},"  caches.",[470,623,624],{"class":480},"match",[470,626,627],{"class":476},"(event.request).",[470,629,630],{"class":480},"then",[470,632,633],{"class":476},"((",[470,635,636],{"class":494},"res",[470,638,498],{"class":476},[470,640,502],{"class":501},[470,642,505],{"class":476},[470,644,645,648,651,654,657],{"class":472,"line":525},[470,646,647],{"class":501},"    return",[470,649,650],{"class":476}," res ",[470,652,653],{"class":501},"||",[470,655,656],{"class":480}," fetch",[470,658,659],{"class":476},"(event.request)\n",[470,661,663],{"class":472,"line":662},4,[470,664,665],{"class":476},"  })\n",[470,667,669],{"class":472,"line":668},5,[470,670,671],{"class":476},")\n",[444,673,675],{"id":674},"_2-network-first最新資料優先","2. Network First（最新資料優先）",[580,677,678,683,688],{},[583,679,680,682],{},[366,681,587],{},"：Page ↓ SW ↓ Server → (Success: Page + Cache) / (Fail: Cache → Page)",[583,684,685,687],{},[366,686,593],{},"：API 動態資料、使用者內容。優先確保資料新鮮度。",[583,689,690,600],{},[366,691,599],{},[407,693,695],{"className":464,"code":694,"language":466,"meta":413,"style":413},"event.respondWith(\n  fetch(event.request)\n    .then((res) => res)\n    .catch(() => caches.match(event.request))\n)\n",[400,696,697,705,712,730,750],{"__ignoreMap":413},[470,698,699,701,703],{"class":472,"line":473},[470,700,610],{"class":476},[470,702,613],{"class":480},[470,704,616],{"class":476},[470,706,707,710],{"class":472,"line":508},[470,708,709],{"class":480},"  fetch",[470,711,659],{"class":476},[470,713,714,717,719,721,723,725,727],{"class":472,"line":525},[470,715,716],{"class":476},"    .",[470,718,630],{"class":480},[470,720,633],{"class":476},[470,722,636],{"class":494},[470,724,498],{"class":476},[470,726,502],{"class":501},[470,728,729],{"class":476}," res)\n",[470,731,732,734,737,740,742,745,747],{"class":472,"line":662},[470,733,716],{"class":476},[470,735,736],{"class":480},"catch",[470,738,739],{"class":476},"(() ",[470,741,502],{"class":501},[470,743,744],{"class":476}," caches.",[470,746,624],{"class":480},[470,748,749],{"class":476},"(event.request))\n",[470,751,752],{"class":472,"line":668},[470,753,671],{"class":476},[444,755,757],{"id":756},"_3-stale-while-revalidate最常用","3. Stale While Revalidate（最常用）",[580,759,760,765,771],{},[583,761,762,764],{},[366,763,587],{},"：Page ↓ SW ↓ Cache → 立即回應，同時 Server → 背景更新 Cache。",[583,766,767,770],{},[366,768,769],{},"特色","：兼顧速度與新鮮度。使用者先拿到舊資料，背景偷偷更新。",[583,772,773,600],{},[366,774,599],{},[407,776,778],{"className":464,"code":777,"language":466,"meta":413,"style":413},"event.respondWith(\n  caches.match(event.request).then((res) => {\n    const fetchPromise = fetch(event.request).then((networkRes) => {\n      caches.open(\"v1\").then((cache) => {\n        cache.put(event.request, networkRes.clone())\n      })\n      return networkRes\n    })\n    return res || fetchPromise\n  })\n)\n",[400,779,780,788,808,837,866,883,889,898,904,916,921],{"__ignoreMap":413},[470,781,782,784,786],{"class":472,"line":473},[470,783,610],{"class":476},[470,785,613],{"class":480},[470,787,616],{"class":476},[470,789,790,792,794,796,798,800,802,804,806],{"class":472,"line":508},[470,791,621],{"class":476},[470,793,624],{"class":480},[470,795,627],{"class":476},[470,797,630],{"class":480},[470,799,633],{"class":476},[470,801,636],{"class":494},[470,803,498],{"class":476},[470,805,502],{"class":501},[470,807,505],{"class":476},[470,809,810,813,817,820,822,824,826,828,831,833,835],{"class":472,"line":525},[470,811,812],{"class":501},"    const",[470,814,816],{"class":815},"sDLfK"," fetchPromise",[470,818,819],{"class":501}," =",[470,821,656],{"class":480},[470,823,627],{"class":476},[470,825,630],{"class":480},[470,827,633],{"class":476},[470,829,830],{"class":494},"networkRes",[470,832,498],{"class":476},[470,834,502],{"class":501},[470,836,505],{"class":476},[470,838,839,842,845,847,850,853,855,857,860,862,864],{"class":472,"line":662},[470,840,841],{"class":476},"      caches.",[470,843,844],{"class":480},"open",[470,846,484],{"class":476},[470,848,849],{"class":487},"\"v1\"",[470,851,852],{"class":476},").",[470,854,630],{"class":480},[470,856,633],{"class":476},[470,858,859],{"class":494},"cache",[470,861,498],{"class":476},[470,863,502],{"class":501},[470,865,505],{"class":476},[470,867,868,871,874,877,880],{"class":472,"line":668},[470,869,870],{"class":476},"        cache.",[470,872,873],{"class":480},"put",[470,875,876],{"class":476},"(event.request, networkRes.",[470,878,879],{"class":480},"clone",[470,881,882],{"class":476},"())\n",[470,884,886],{"class":472,"line":885},6,[470,887,888],{"class":476},"      })\n",[470,890,892,895],{"class":472,"line":891},7,[470,893,894],{"class":501},"      return",[470,896,897],{"class":476}," networkRes\n",[470,899,901],{"class":472,"line":900},8,[470,902,903],{"class":476},"    })\n",[470,905,907,909,911,913],{"class":472,"line":906},9,[470,908,647],{"class":501},[470,910,650],{"class":476},[470,912,653],{"class":501},[470,914,915],{"class":476}," fetchPromise\n",[470,917,919],{"class":472,"line":918},10,[470,920,665],{"class":476},[470,922,924],{"class":472,"line":923},11,[470,925,671],{"class":476},[378,927],{},[381,929,930],{"id":930},"一個很多人會誤解的重點",[362,932,933,934,937],{},"Service Worker ",[366,935,936],{},"並不是替代 Server","。它的角色是多了一層「控制權」，讓你可以決定何時使用快取、何時打 API、何時離線回應以及何時背景更新。理解這層代理機制，你就真正掌握了 SW。",[378,939],{},[381,941,942],{"id":942},"結語",[362,944,945,946],{},"Service Worker 的核心其實只有一句話：",[366,947,948],{},"攔截請求，決定回應來源。",[362,950,951],{},"只要你理解了這個 Request Flow，未來在設計 PWA、優化效能或部署 SPA 時，就能有清晰的架構思維，而不只是「照框架設定」。",[953,954,955],"style",{},"html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}",{"title":413,"searchDepth":508,"depth":508,"links":957},[958,959,960,965,970,971],{"id":383,"depth":508,"text":384},{"id":420,"depth":508,"text":421},{"id":435,"depth":508,"text":436,"children":961},[962,963,964],{"id":446,"depth":525,"text":447},{"id":457,"depth":525,"text":458},{"id":531,"depth":525,"text":532},{"id":570,"depth":508,"text":571,"children":966},[967,968,969],{"id":577,"depth":525,"text":578},{"id":674,"depth":525,"text":675},{"id":756,"depth":525,"text":757},{"id":930,"depth":508,"text":930},{"id":942,"depth":508,"text":942},"從請求流程圖到實戰策略，完整理解 Service Worker 如何攔截請求、操作快取並打造離線優先的 PWA 體驗。","md",null,{"tags":976,"category":203,"date":981},[977,978,859,979,980],"pwa","service-worker","web-performance","frontend","2026-02-13",true,{"title":223,"description":972},"Nu0ZQNt8-Pz8MtbUibSYG-Ux84cZYHf3e3bTi8Fdw-Q",[986,988],{"title":219,"path":220,"stem":221,"description":987,"children":-1},"掌握高效操作 DOM 的技巧，了解其運作機制，並學習如何優化 Web 應用的效能。",{"title":227,"path":228,"stem":229,"description":989,"children":-1},"一次搞懂 CSR、SSR、SSG 的差異、運作流程與適用情境，幫助你在 Nuxt、Vue 或現代前端專案中選擇最合適的渲染策略。",1776690845506]