{"id":83,"date":"2026-06-17T10:44:09","date_gmt":"2026-06-17T02:44:09","guid":{"rendered":"https:\/\/yykcj.com\/?p=83"},"modified":"2026-06-17T10:44:09","modified_gmt":"2026-06-17T02:44:09","slug":"service-worker-%e4%b8%8e-pwa-%e5%ae%8c%e6%95%b4%e6%8c%87%e5%8d%97%ef%bc%9a%e4%bb%8e%e9%9b%b6%e6%9e%84%e5%bb%ba%e7%a6%bb%e7%ba%bf%e4%bc%98%e5%85%88%e7%9a%84%e7%8e%b0%e4%bb%a3-web-%e5%ba%94%e7%94%a8","status":"publish","type":"post","link":"https:\/\/yykcj.com\/?p=83","title":{"rendered":"Service Worker \u4e0e PWA \u5b8c\u6574\u6307\u5357\uff1a\u4ece\u96f6\u6784\u5efa\u79bb\u7ebf\u4f18\u5148\u7684\u73b0\u4ee3 Web \u5e94\u7528"},"content":{"rendered":"<h2>\u524d\u8a00<\/h2>\n<p>Progressive Web App\uff08PWA\uff09\u5df2\u6210\u4e3a\u63d0\u5347 Web \u5e94\u7528\u4f53\u9a8c\u7684\u5173\u952e\u6280\u672f\uff0c\u800c Service Worker \u662f\u5176\u6838\u5fc3\u5f15\u64ce\u3002\u5b83\u80fd\u62e6\u622a\u7f51\u7edc\u8bf7\u6c42\u3001\u7ba1\u7406\u7f13\u5b58\u3001\u5b9e\u73b0\u79bb\u7ebf\u8bbf\u95ee\uff0c\u751a\u81f3\u652f\u6301\u540e\u53f0\u540c\u6b65\u4e0e\u63a8\u9001\u901a\u77e5\u3002\u7136\u800c\uff0cService Worker \u7684\u751f\u547d\u5468\u671f\u590d\u6742\uff0c\u7f13\u5b58\u7b56\u7565\u9009\u62e9\u4e0d\u5f53\u5bb9\u6613\u5bfc\u81f4\u8d44\u6e90\u8fc7\u671f\u6216\u7248\u672c\u6df7\u4e71\u3002\u672c\u6587\u5c06\u4ece\u96f6\u5f00\u59cb\uff0c\u5e26\u4f60\u6784\u5efa\u4e00\u4e2a\u5b8c\u6574\u7684 PWA\uff0c\u6db5\u76d6\u6ce8\u518c\u3001\u5b89\u88c5\u3001\u6fc0\u6d3b\u3001\u62e6\u622a\u8bf7\u6c42\u3001\u7f13\u5b58\u66f4\u65b0\u7b49\u5168\u6d41\u7a0b\uff0c\u5e76\u5206\u4eab\u751f\u4ea7\u73af\u5883\u4e0b\u7684\u6700\u4f73\u5b9e\u8df5\u3002<\/p>\n<h2>1. \u9879\u76ee\u521d\u59cb\u5316<\/h2>\n<p>\u521b\u5efa\u4e00\u4e2a\u7b80\u5355\u7684 HTML \u9875\u9762\uff0c\u5305\u542b\u4e00\u4e2a\u56fe\u6807\u548c\u6e05\u5355\u6587\u4ef6\u3002<\/p>\n<pre><code class=\"language-bash\">\nmkdir pwa-demo &amp;&amp; cd pwa-demo\n<\/code><\/pre>\n<p>\u521b\u5efa <code>index.html<\/code>\uff1a<\/p>\n<pre><code class=\"language-html\">\n&lt;!DOCTYPE html&gt;\n&lt;html lang=&quot;zh-CN&quot;&gt;\n&lt;head&gt;\n    &lt;meta charset=&quot;UTF-8&quot;&gt;\n    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;\n    &lt;title&gt;PWA \u6f14\u793a&lt;\/title&gt;\n    &lt;link rel=&quot;manifest&quot; href=&quot;manifest.json&quot;&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;h1&gt;Hello, PWA!&lt;\/h1&gt;\n    &lt;img src=&quot;icon.png&quot; alt=&quot;icon&quot; width=&quot;100&quot;&gt;\n    &lt;script src=&quot;app.js&quot;&gt;&lt;\/script&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;\n<\/code><\/pre>\n<p>\u521b\u5efa <code>manifest.json<\/code>\uff1a<\/p>\n<pre><code class=\"language-json\">\n{\n    &quot;name&quot;: &quot;PWA Demo&quot;,\n    &quot;short_name&quot;: &quot;PWADemo&quot;,\n    &quot;start_url&quot;: &quot;\/&quot;,\n    &quot;display&quot;: &quot;standalone&quot;,\n    &quot;background_color&quot;: &quot;#ffffff&quot;,\n    &quot;theme_color&quot;: &quot;#000000&quot;,\n    &quot;icons&quot;: [\n        {\n            &quot;src&quot;: &quot;icon-192.png&quot;,\n            &quot;sizes&quot;: &quot;192x192&quot;,\n            &quot;type&quot;: &quot;image\/png&quot;\n        },\n        {\n            &quot;src&quot;: &quot;icon-512.png&quot;,\n            &quot;sizes&quot;: &quot;512x512&quot;,\n            &quot;type&quot;: &quot;image\/png&quot;\n        }\n    ]\n}\n<\/code><\/pre>\n<p>> <strong>\u6ce8\u610f<\/strong>\uff1a\u56fe\u6807\u6587\u4ef6\u9700\u51c6\u5907 192&#215;192 \u548c 512&#215;512 \u7684 PNG \u56fe\u7247\uff0c\u53ef\u4e34\u65f6\u7528\u5360\u4f4d\u56fe\u4ee3\u66ff\u3002<\/p>\n<h2>2. \u6ce8\u518c Service Worker<\/h2>\n<p>\u521b\u5efa <code>sw.js<\/code> \u6587\u4ef6\uff0c\u8fd9\u662f Service Worker \u7684\u811a\u672c\u3002\u5728 <code>app.js<\/code> \u4e2d\u6ce8\u518c\u5b83\u3002<\/p>\n<pre><code class=\"language-javascript\">\n\/\/ app.js\nif (&#x27;serviceWorker&#x27; in navigator) {\n    navigator.serviceWorker.register(&#x27;\/sw.js&#x27;)\n        .then(registration =&gt; {\n            console.log(&#x27;SW \u6ce8\u518c\u6210\u529f:&#x27;, registration.scope);\n        })\n        .catch(error =&gt; {\n            console.log(&#x27;SW \u6ce8\u518c\u5931\u8d25:&#x27;, error);\n        });\n} else {\n    console.log(&#x27;\u5f53\u524d\u6d4f\u89c8\u5668\u4e0d\u652f\u6301 Service Worker&#x27;);\n}\n<\/code><\/pre>\n<p>> <strong>\u6ce8\u610f<\/strong>\uff1a<code>sw.js<\/code> \u5fc5\u987b\u653e\u5728\u7ad9\u70b9\u6839\u76ee\u5f55\uff08\u6216\u540c\u57df\u4e0b\uff09\uff0c\u4e14 scope \u9ed8\u8ba4\u4e3a\u811a\u672c\u6240\u5728\u76ee\u5f55\u3002\u5efa\u8bae\u653e\u5728\u6839\u76ee\u5f55\u4ee5\u63a7\u5236\u6574\u4e2a\u7ad9\u70b9\u3002<\/p>\n<h2>3. \u751f\u547d\u5468\u671f\u4e0e\u6838\u5fc3\u4e8b\u4ef6<\/h2>\n<p>Service Worker \u6709\u4e09\u4e2a\u5173\u952e\u4e8b\u4ef6\uff1a<code>install<\/code>\u3001<code>activate<\/code> \u548c <code>fetch<\/code>\u3002<\/p>\n<h3>3.1 install \u4e8b\u4ef6\uff1a\u9884\u7f13\u5b58\u9759\u6001\u8d44\u6e90<\/h3>\n<p>\u5728 <code>sw.js<\/code> \u4e2d\u76d1\u542c <code>install<\/code> \u4e8b\u4ef6\uff0c\u901a\u5e38\u5728\u6b64\u5904\u9884\u7f13\u5b58\u5e94\u7528\u5916\u58f3\uff08App Shell\uff09\u6240\u9700\u7684\u9759\u6001\u8d44\u6e90\u3002<\/p>\n<pre><code class=\"language-javascript\">\n\/\/ sw.js\nconst CACHE_NAME = &#x27;pwa-demo-v1&#x27;;\nconst urlsToCache = [\n    &#x27;\/&#x27;,\n    &#x27;\/index.html&#x27;,\n    &#x27;\/icon.png&#x27;,\n    &#x27;\/app.js&#x27;\n];\n\nself.addEventListener(&#x27;install&#x27;, event =&gt; {\n    event.waitUntil(\n        caches.open(CACHE_NAME)\n            .then(cache =&gt; {\n                console.log(&#x27;\u7f13\u5b58\u5df2\u6253\u5f00&#x27;);\n                return cache.addAll(urlsToCache);\n            })\n            .catch(err =&gt; console.error(&#x27;\u7f13\u5b58\u5931\u8d25:&#x27;, err))\n    );\n});\n<\/code><\/pre>\n<p>> <strong>\u6ce8\u610f<\/strong>\uff1a<code>cache.addAll()<\/code> \u662f\u539f\u5b50\u64cd\u4f5c\uff0c\u4efb\u4e00\u8bf7\u6c42\u5931\u8d25\u5219\u6574\u4e2a\u7f13\u5b58\u5931\u8d25\u3002\u5efa\u8bae\u5148\u5355\u72ec\u7f13\u5b58\u5173\u952e\u8d44\u6e90\uff0c\u6216\u4f7f\u7528 try-catch\u3002<\/p>\n<h3>3.2 activate \u4e8b\u4ef6\uff1a\u6e05\u7406\u65e7\u7f13\u5b58<\/h3>\n<p>\u5f53\u65b0 Service Worker \u6fc0\u6d3b\u65f6\uff0c\u5e94\u5220\u9664\u65e7\u7248\u672c\u7684\u7f13\u5b58\uff0c\u907f\u514d\u78c1\u76d8\u7a7a\u95f4\u6d6a\u8d39\u3002<\/p>\n<pre><code class=\"language-javascript\">\nself.addEventListener(&#x27;activate&#x27;, event =&gt; {\n    const cacheWhitelist = [CACHE_NAME];\n    event.waitUntil(\n        caches.keys().then(cacheNames =&gt; {\n            return Promise.all(\n                cacheNames.map(cacheName =&gt; {\n                    if (cacheWhitelist.indexOf(cacheName) === -1) {\n                        console.log(&#x27;\u5220\u9664\u65e7\u7f13\u5b58:&#x27;, cacheName);\n                        return caches.delete(cacheName);\n                    }\n                })\n            );\n        })\n    );\n});\n<\/code><\/pre>\n<h3>3.3 fetch \u4e8b\u4ef6\uff1a\u62e6\u622a\u8bf7\u6c42\u5e76\u8fd4\u56de\u7f13\u5b58<\/h3>\n<p>\u8fd9\u662f\u6838\u5fc3\u90e8\u5206\uff0c\u51b3\u5b9a\u7f13\u5b58\u7b56\u7565\u3002\u5e38\u7528\u7b56\u7565\u6709\uff1a<\/p>\n<ul>\n<li><strong>Cache First<\/strong>\uff1a\u4f18\u5148\u4ece\u7f13\u5b58\u83b7\u53d6\uff0c\u5931\u8d25\u5219\u8bf7\u6c42\u7f51\u7edc\u3002<\/li>\n<li><strong>Network First<\/strong>\uff1a\u4f18\u5148\u7f51\u7edc\uff0c\u5931\u8d25\u5219\u56de\u9000\u7f13\u5b58\u3002<\/li>\n<li><strong>Stale While Revalidate<\/strong>\uff1a\u540c\u65f6\u8fd4\u56de\u7f13\u5b58\u548c\u7f51\u7edc\u66f4\u65b0\u3002<\/li>\n<\/ul>\n<p>\u4ee5\u4e0b\u5b9e\u73b0 Cache First \u7b56\u7565\uff1a<\/p>\n<pre><code class=\"language-javascript\">\nself.addEventListener(&#x27;fetch&#x27;, event =&gt; {\n    event.respondWith(\n        caches.match(event.request)\n            .then(response =&gt; {\n                if (response) {\n                    return response; \/\/ \u7f13\u5b58\u547d\u4e2d\n                }\n                return fetch(event.request); \/\/ \u8bf7\u6c42\u7f51\u7edc\n            })\n            .catch(() =&gt; {\n                \/\/ \u79bb\u7ebf\u4e14\u65e0\u7f13\u5b58\u65f6\u8fd4\u56de\u9ed8\u8ba4\u9875\n                return caches.match(&#x27;\/offline.html&#x27;);\n            })\n    );\n});\n<\/code><\/pre>\n<p>> <strong>\u6ce8\u610f<\/strong>\uff1a\u5bf9\u4e8e API \u8bf7\u6c42\uff08\u5982 <code>\/api\/data<\/code>\uff09\uff0c\u901a\u5e38\u4f7f\u7528 Network First \u6216 Stale While Revalidate \u4ee5\u4fdd\u8bc1\u6570\u636e\u65b0\u9c9c\u3002\u53ef\u9488\u5bf9\u4e0d\u540c URL \u6a21\u5f0f\u4f7f\u7528\u4e0d\u540c\u7b56\u7565\u3002<\/p>\n<h2>4. \u66f4\u65b0 Service Worker<\/h2>\n<p>\u5f53 <code>sw.js<\/code> \u5185\u5bb9\u53d8\u5316\uff08\u5b57\u8282\u7ea7\u522b\uff09\uff0c\u6d4f\u89c8\u5668\u4f1a\u68c0\u6d4b\u5230\u5e76\u89e6\u53d1\u66f4\u65b0\u3002\u4f46\u65b0 SW \u4e0d\u4f1a\u7acb\u5373\u63a5\u7ba1\uff0c\u9700\u7b49\u5f85\u65e7 SW \u63a7\u5236\u7684\u6240\u6709\u9875\u9762\u5173\u95ed\u3002\u53ef\u624b\u52a8\u8c03\u7528 <code>self.skipWaiting()<\/code> \u548c <code>clients.claim()<\/code> \u5b9e\u73b0\u7acb\u5373\u66f4\u65b0\u3002<\/p>\n<pre><code class=\"language-javascript\">\n\/\/ \u5728 install \u4e8b\u4ef6\u4e2d\nself.addEventListener(&#x27;install&#x27;, event =&gt; {\n    self.skipWaiting(); \/\/ \u7acb\u5373\u6fc0\u6d3b\u65b0 SW\n    \/\/ ... \u7f13\u5b58\u903b\u8f91\n});\n\n\/\/ \u5728 activate \u4e8b\u4ef6\u4e2d\nself.addEventListener(&#x27;activate&#x27;, event =&gt; {\n    clients.claim(); \/\/ \u7acb\u5373\u63a7\u5236\u6240\u6709\u5ba2\u6237\u7aef\n    \/\/ ... \u6e05\u7406\u7f13\u5b58\n});\n<\/code><\/pre>\n<p>> <strong>\u6700\u4f73\u5b9e\u8df5<\/strong>\uff1a\u901a\u5e38\u4e0d\u63a8\u8350\u7acb\u5373\u6fc0\u6d3b\uff0c\u800c\u662f\u901a\u77e5\u7528\u6237\u6709\u65b0\u7248\u672c\uff0c\u8ba9\u7528\u6237\u624b\u52a8\u5237\u65b0\u3002\u53ef\u901a\u8fc7\u76d1\u542c <code>controllerchange<\/code> \u4e8b\u4ef6\u5b9e\u73b0\u3002<\/p>\n<h2>5. \u540e\u53f0\u540c\u6b65\u4e0e\u63a8\u9001\u901a\u77e5<\/h2>\n<h3>5.1 \u540e\u53f0\u540c\u6b65<\/h3>\n<p>\u5f53\u7528\u6237\u79bb\u7ebf\u65f6\u63d0\u4ea4\u7684\u8868\u5355\uff0c\u53ef\u5728\u7f51\u7edc\u6062\u590d\u540e\u81ea\u52a8\u540c\u6b65\u3002<\/p>\n<pre><code class=\"language-javascript\">\n\/\/ \u6ce8\u518c\u540c\u6b65\u4e8b\u4ef6\nnavigator.serviceWorker.ready.then(registration =&gt; {\n    registration.sync.register(&#x27;sync-form-data&#x27;);\n});\n\n\/\/ sw.js \u4e2d\u76d1\u542c\nself.addEventListener(&#x27;sync&#x27;, event =&gt; {\n    if (event.tag === &#x27;sync-form-data&#x27;) {\n        event.waitUntil(syncFormData());\n    }\n});\n\nasync function syncFormData() {\n    \/\/ \u4ece IndexedDB \u8bfb\u53d6\u5f85\u540c\u6b65\u6570\u636e\u5e76\u53d1\u9001\u8bf7\u6c42\n    const data = await getPendingData();\n    await fetch(&#x27;\/api\/submit&#x27;, { method: &#x27;POST&#x27;, body: data });\n}\n<\/code><\/pre>\n<h3>5.2 \u63a8\u9001\u901a\u77e5<\/h3>\n<p>\u9700\u8981\u670d\u52a1\u7aef\u914d\u5408\uff0c\u8fd9\u91cc\u53ea\u5c55\u793a\u5ba2\u6237\u7aef\u63a5\u6536\u3002<\/p>\n<pre><code class=\"language-javascript\">\n\/\/ \u8bf7\u6c42\u6743\u9650\nNotification.requestPermission().then(permission =&gt; {\n    if (permission === &#x27;granted&#x27;) {\n        \/\/ \u8ba2\u9605\u63a8\u9001\n    }\n});\n\n\/\/ sw.js \u4e2d\u76d1\u542c\u63a8\u9001\u4e8b\u4ef6\nself.addEventListener(&#x27;push&#x27;, event =&gt; {\n    const data = event.data.json();\n    const options = {\n        body: data.body,\n        icon: &#x27;\/icon.png&#x27;\n    };\n    event.waitUntil(\n        self.registration.showNotification(data.title, options)\n    );\n});\n<\/code><\/pre>\n<h2>6. \u5e38\u89c1\u9677\u9631\u4e0e\u8c03\u8bd5<\/h2>\n<ul>\n<li><strong>HTTPS \u8981\u6c42<\/strong>\uff1aService Worker \u53ea\u80fd\u5728 HTTPS \u6216 localhost \u4e0b\u5de5\u4f5c\u3002<\/li>\n<li><strong>\u4f5c\u7528\u57df\u9650\u5236<\/strong>\uff1a<code>sw.js<\/code> \u53ea\u80fd\u63a7\u5236\u5176\u6240\u5728\u76ee\u5f55\u53ca\u5b50\u76ee\u5f55\u4e0b\u7684\u9875\u9762\u3002<\/li>\n<li><strong>\u7f13\u5b58\u66f4\u65b0<\/strong>\uff1a\u4fee\u6539 <code>sw.js<\/code> \u540e\u6d4f\u89c8\u5668\u53ef\u80fd\u4e0d\u66f4\u65b0\uff0c\u9700\u5728\u5f00\u53d1\u8005\u5de5\u5177\u4e2d\u52fe\u9009\u201cUpdate on reload\u201d\u3002<\/li>\n<li><strong>\u8c03\u8bd5\u5de5\u5177<\/strong>\uff1aChrome DevTools \u7684 Application \u9762\u677f\u53ef\u67e5\u770b SW \u72b6\u6001\u3001\u7f13\u5b58\u5185\u5bb9\u53ca\u6e05\u9664\u7f13\u5b58\u3002<\/li>\n<\/ul>\n<h2>7. \u5b8c\u6574\u793a\u4f8b\u4ee3\u7801<\/h2>\n<p>\u4ee5\u4e0b\u662f\u6574\u5408\u540e\u7684 <code>sw.js<\/code>\uff1a<\/p>\n<pre><code class=\"language-javascript\">\nconst CACHE_NAME = &#x27;pwa-demo-v2&#x27;;\nconst urlsToCache = [\n    &#x27;\/&#x27;,\n    &#x27;\/index.html&#x27;,\n    &#x27;\/icon.png&#x27;,\n    &#x27;\/app.js&#x27;,\n    &#x27;\/offline.html&#x27;\n];\n\nself.addEventListener(&#x27;install&#x27;, event =&gt; {\n    self.skipWaiting();\n    event.waitUntil(\n        caches.open(CACHE_NAME)\n            .then(cache =&gt; cache.addAll(urlsToCache))\n    );\n});\n\nself.addEventListener(&#x27;activate&#x27;, event =&gt; {\n    clients.claim();\n    event.waitUntil(\n        caches.keys().then(cacheNames =&gt; {\n            return Promise.all(\n                cacheNames.map(cacheName =&gt; {\n                    if (cacheName !== CACHE_NAME) {\n                        return caches.delete(cacheName);\n                    }\n                })\n            );\n        })\n    );\n});\n\nself.addEventListener(&#x27;fetch&#x27;, event =&gt; {\n    event.respondWith(\n        caches.match(event.request)\n            .then(response =&gt; response || fetch(event.request))\n            .catch(() =&gt; caches.match(&#x27;\/offline.html&#x27;))\n    );\n});\n<\/code><\/pre>\n<h2>\u603b\u7ed3<\/h2>\n<p>\u901a\u8fc7\u672c\u6587\uff0c\u4f60\u5df2\u638c\u63e1 Service Worker \u7684\u6838\u5fc3\u6982\u5ff5\u4e0e\u5b9e\u73b0\uff1a<\/p>\n<ul>\n<li>\u6ce8\u518c\u4e0e\u751f\u547d\u5468\u671f\u7ba1\u7406<\/li>\n<li>\u7f13\u5b58\u7b56\u7565\uff08Cache First\u3001Network First \u7b49\uff09<\/li>\n<li>\u66f4\u65b0\u673a\u5236\u4e0e\u7acb\u5373\u6fc0\u6d3b\u6280\u5de7<\/li>\n<li>\u540e\u53f0\u540c\u6b65\u4e0e\u63a8\u9001\u901a\u77e5\u5165\u95e8<\/li>\n<li>\u5e38\u89c1\u9677\u9631\u4e0e\u8c03\u8bd5\u65b9\u6cd5<\/li>\n<\/ul>\n<p>\u4e0b\u4e00\u6b65\uff0c\u53ef\u4ee5\u63a2\u7d22 Workbox \u5e93\u7b80\u5316 Service Worker \u7f16\u5199\uff0c\u6216\u7ed3\u5408 IndexedDB \u5b9e\u73b0\u66f4\u590d\u6742\u7684\u79bb\u7ebf\u6570\u636e\u7ba1\u7406\u3002PWA \u7684\u672a\u6765\u8fd8\u5305\u62ec Web \u5305\u3001\u6d41\u5f0f\u5b89\u88c5\u7b49\u65b0\u7279\u6027\uff0c\u503c\u5f97\u6301\u7eed\u5173\u6ce8\u3002<\/p>\n<p>\u5e0c\u671b\u672c\u6587\u80fd\u4e3a\u4f60\u7684 PWA \u5b9e\u8df5\u63d0\u4f9b\u6e05\u6670\u6307\u5f15\u3002\u5982\u6709\u7591\u95ee\uff0c\u6b22\u8fce\u5728\u8bc4\u8bba\u533a\u4ea4\u6d41\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u672c\u6587\u624b\u628a\u624b\u6559\u4f60\u4f7f\u7528 Service Worker \u5b9e\u73b0\u79bb\u7ebf\u7f13\u5b58\u3001\u540e\u53f0\u540c\u6b65\u4e0e\u63a8\u9001\u901a\u77e5\uff0c\u6784\u5efa\u4e00\u4e2a\u5b8c\u6574\u53ef\u8fd0\u884c\u7684 PWA \u5e94\u7528\u3002\u6db5\u76d6\u751f\u547d\u5468\u671f\u3001\u7f13\u5b58\u7b56\u7565\u3001\u66f4\u65b0\u673a\u5236\u7b49\u6838\u5fc3\u6982\u5ff5\uff0c\u5e76\u63d0\u4f9b\u6700\u4f73\u5b9e\u8df5\u4e0e\u5e38\u89c1\u9677\u9631\u3002<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,4],"tags":[47,46,49,50,48],"class_list":["post-83","post","type-post","status-publish","format-standard","hentry","category-3","category-4","tag-pwa","tag-service-worker","tag-49","tag-web","tag-48"],"_links":{"self":[{"href":"https:\/\/yykcj.com\/index.php?rest_route=\/wp\/v2\/posts\/83","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/yykcj.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/yykcj.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/yykcj.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/yykcj.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=83"}],"version-history":[{"count":0,"href":"https:\/\/yykcj.com\/index.php?rest_route=\/wp\/v2\/posts\/83\/revisions"}],"wp:attachment":[{"href":"https:\/\/yykcj.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=83"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/yykcj.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=83"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/yykcj.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=83"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}