Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Is the service worker supposed to cache itself with the PWA template?

Discussion in 'Web' started by ComputerKim, Feb 23, 2023.

  1. ComputerKim

    ComputerKim

    Joined:
    Jan 6, 2019
    Posts:
    15
    I ran into a caching issue after switching to the PWA template, it was caching the old version of my game, even if I turned all caching off for the web server.

    It seems the service worker caches itself and then servers the old version to the client.

    Is this a bug or is there something I'm missing?
     
  2. MajorWolph

    MajorWolph

    Joined:
    Apr 28, 2018
    Posts:
    24
    Im also experiencing this issue. I’ve tried with name files as hash but it didn’t fix it. Did you manage to find a solution?
     
  3. ComputerKim

    ComputerKim

    Joined:
    Jan 6, 2019
    Posts:
    15
    This is how I fixed it:

    Code (CSharp):
    1. #if UNITY_EDITOR
    2.  
    3. using System.IO;
    4. using UnityEditor;
    5. using UnityEditor.Callbacks;
    6.  
    7. public class FixPWA {
    8.     [PostProcessBuild(1)]
    9.     public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject) {
    10.         FixIndex(pathToBuiltProject);
    11.         FixServiceWorker(pathToBuiltProject);
    12.     }
    13.  
    14.     public static void FixIndex(string path) {
    15.         path = $"{path}/index.html";
    16.         if (!File.Exists(path)) return;
    17.         var index = File.ReadAllText(path);
    18.         if (index.Contains("register(\"ServiceWorker.js\").")) return;
    19.        
    20.         // Fix title
    21.         index = index.Replace("Unity WebGL Player | ", "");
    22.        
    23.         // Prompt user to reload new version
    24.         index = index.Replace("register(\"ServiceWorker.js\");",
    25.             @"register('ServiceWorker.js').then(reg => {
    26.            reg.onupdatefound = () => {
    27.              const installingWorker = reg.installing;
    28.              installingWorker.onstatechange = () => {
    29.                if (installingWorker.state === 'installed' && navigator.serviceWorker.controller) {
    30.                  if (confirm('An update is available, do you want to reload?')) {
    31.                    location.reload();
    32.                  }
    33.                }
    34.              };
    35.            };
    36.          });");
    37.        
    38.         File.WriteAllText(path, index);
    39.     }
    40.    
    41.     public static void FixServiceWorker(string path) {
    42.         path = $"{path}/ServiceWorker.js";
    43.         if (!File.Exists(path)) return;
    44.         var sw = File.ReadAllText(path);
    45.         if (sw.Contains("skipWaiting")) return;
    46.        
    47.         // Don't cache ServiceWorker.js
    48.         sw = sw.Replace(
    49.             "self.addEventListener('fetch', function (e) {",
    50.             @"self.addEventListener('fetch', function (e) {
    51.    if (e.request.url.endsWith('/ServiceWorker.js')) { return }
    52. ");
    53.  
    54.         // Don't wait
    55.         sw = sw.Replace(
    56.             "console.log('[Service Worker] Install');",
    57.             @"console.log('[Service Worker] Install');
    58.    self.skipWaiting();");
    59.  
    60.         // Clear old cache
    61.         sw = sw.Replace(
    62.             "e.waitUntil((async function () {",
    63.             @"e.waitUntil((async function () {
    64.      for (let name of (await caches.keys()))
    65.        caches.delete(name);
    66. ");
    67.        
    68.         File.WriteAllText(path, sw);
    69.     }
    70. }
    71.  
    72. #endif