Browse Source

feat: support debugging PWA in dev (#4853)

* feat: support enabling pwa in dev

* enable workbox debug

* add prebuild script

* fix lint
David Luzar 2 years ago
parent
commit
0ef202f2df
6 changed files with 78 additions and 13 deletions
  1. 9 0
      .env.development
  2. 2 1
      package.json
  3. 16 0
      public/index.html
  4. 26 11
      public/service-worker.js
  5. 20 0
      scripts/prebuild.js
  6. 5 1
      src/serviceWorker.tsx

+ 9 - 0
.env.development

@@ -11,3 +11,12 @@ REACT_APP_WS_SERVER_URL=http://localhost:3002
 REACT_APP_PORTAL_URL=
 
 REACT_APP_FIREBASE_CONFIG='{"apiKey":"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8","authDomain":"excalidraw-oss-dev.firebaseapp.com","projectId":"excalidraw-oss-dev","storageBucket":"excalidraw-oss-dev.appspot.com","messagingSenderId":"664559512677","appId":"1:664559512677:web:a385181f2928d328a7aa8c"}'
+
+# put these in your .env.local, or make sure you don't commit!
+# must be lowercase `true` when turned on
+#
+# whether to enable Service Workers in development
+REACT_APP_DEV_ENABLE_SW=
+# whether to disable live reload / HMR. Usuaully what you want to do when
+# debugging Service Workers.
+REACT_APP_DEV_DISABLE_LIVE_RELOAD=

+ 2 - 1
package.json

@@ -94,7 +94,8 @@
     "build:app:docker": "REACT_APP_DISABLE_SENTRY=true react-scripts build",
     "build:app": "REACT_APP_GIT_SHA=$VERCEL_GIT_COMMIT_SHA react-scripts build",
     "build:version": "node ./scripts/build-version.js",
-    "build": "yarn build:app && yarn build:version",
+    "build:prebuild": "node ./scripts/prebuild.js",
+    "build": "yarn build:prebuild && yarn build:app && yarn build:version",
     "eject": "react-scripts eject",
     "fix:code": "yarn test:code --fix",
     "fix:other": "yarn prettier --write",

+ 16 - 0
public/index.html

@@ -98,6 +98,22 @@
     />
 
     <link rel="stylesheet" href="fonts.css" type="text/css" />
+    <% if (process.env.REACT_APP_DEV_DISABLE_LIVE_RELOAD === "true") { %>
+    <script>
+      {
+        const _WebSocket = window.WebSocket;
+        window.WebSocket = function (url) {
+          if (/ws:\/\/localhost:.+?\/sockjs-node/.test(url)) {
+            console.info(
+              "[!!!] Live reload is disabled via process.env.REACT_APP_DEV_DISABLE_LIVE_RELOAD [!!!]",
+            );
+          } else {
+            return new _WebSocket(url);
+          }
+        };
+      }
+    </script>
+    <% } %>
     <script>
       window.EXCALIDRAW_ASSET_PATH = "/";
       // setting this so that libraries installation reuses this window tab.

+ 26 - 11
src/service-worker.js → public/service-worker.js

@@ -17,11 +17,23 @@
  * See https://goo.gl/2aRDsh
  */
 
-importScripts("/workbox/workbox-sw.js");
+// in dev, `process` is undefined because this file is not compiled until build
+const IS_DEVELOPMENT =
+  typeof process === "undefined" || process.env.NODE_ENV !== "production";
 
-workbox.setConfig({
-  modulePathPrefix: "/workbox/",
-});
+if (IS_DEVELOPMENT) {
+  importScripts(
+    "https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js",
+  );
+  workbox.setConfig({
+    debug: true,
+  });
+} else {
+  importScripts("/workbox/workbox-sw.js");
+  workbox.setConfig({
+    modulePathPrefix: "/workbox/",
+  });
+}
 
 self.addEventListener("message", (event) => {
   if (event.data && event.data.type === "SKIP_WAITING") {
@@ -30,14 +42,17 @@ self.addEventListener("message", (event) => {
 });
 
 workbox.core.clientsClaim();
-workbox.precaching.precacheAndRoute(self.__WB_MANIFEST);
 
-workbox.routing.registerNavigationRoute(
-  workbox.precaching.getCacheKeyForURL("./index.html"),
-  {
-    blacklist: [/^\/_/, /\/[^/?]+\.[^/]+$/],
-  },
-);
+if (!IS_DEVELOPMENT) {
+  workbox.precaching.precacheAndRoute(self.__WB_MANIFEST);
+
+  workbox.routing.registerNavigationRoute(
+    workbox.precaching.getCacheKeyForURL("./index.html"),
+    {
+      blacklist: [/^\/_/, /\/[^/?]+\.[^/]+$/],
+    },
+  );
+}
 
 // Cache relevant font files
 workbox.routing.registerRoute(

+ 20 - 0
scripts/prebuild.js

@@ -0,0 +1,20 @@
+const fs = require("fs");
+
+// for development purposes we want to have the service-worker.js file
+// accessible from the public folder. On build though, we need to compile it
+// and CRA expects that file to be in src/ folder.
+const moveServiceWorkerScript = () => {
+  const oldPath = "./public/service-worker.js";
+  const newPath = "./src/service-worker.js";
+
+  fs.rename(oldPath, newPath, (error) => {
+    if (error) {
+      throw error;
+    }
+    console.info("public/service-worker.js moved to src/");
+  });
+};
+
+// -----------------------------------------------------------------------------
+
+moveServiceWorkerScript();

+ 5 - 1
src/serviceWorker.tsx

@@ -26,7 +26,11 @@ type Config = {
 };
 
 export const register = (config?: Config) => {
-  if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
+  if (
+    (process.env.NODE_ENV === "production" ||
+      process.env.REACT_APP_DEV_ENABLE_SW?.toLowerCase() === "true") &&
+    "serviceWorker" in navigator
+  ) {
     // The URL constructor is available in all browsers that support SW.
     const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
     if (publicUrl.origin !== window.location.origin) {