From 8b426ad9a9c71d5113baa367bb0d25ff0bce0567 Mon Sep 17 00:00:00 2001
From: Jeff Posnick <jeffy@google.com>
Date: Fri, 19 May 2017 17:26:12 -0700
Subject: [PATCH 1/2] Provide a no-op SW that will be served by the dev
 environment.

---
 .../template/public/service-worker.js           | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 packages/react-scripts/template/public/service-worker.js

diff --git a/packages/react-scripts/template/public/service-worker.js b/packages/react-scripts/template/public/service-worker.js
new file mode 100644
index 00000000000..9ec515ec5f9
--- /dev/null
+++ b/packages/react-scripts/template/public/service-worker.js
@@ -0,0 +1,17 @@
+// This service worker file is effectively a 'no-op' that will reset any
+// previous service worker registered for the same host:port combination.
+// In the production build, this file is replaced with an actual service worker
+// file that will precache your site's local assets.
+// See https://github.com/facebookincubator/create-react-app/issues/2272#issuecomment-302832432
+
+self.addEventListener('install', () => self.skipWaiting());
+
+self.addEventListener('activate', () => {
+  self.clients.matchAll({ type: 'window' }).then(windowClients => {
+    for (let windowClient of windowClients) {
+      // Force open pages to refresh, so that they have a chance to load the
+      // fresh navigation response from the local dev server.
+      windowClient.navigate(windowClient.url);
+    }
+  });
+});

From e5864b0be99f881dd2fd7ee61868e74abbf4b599 Mon Sep 17 00:00:00 2001
From: Dan Abramov <dan.abramov@gmail.com>
Date: Sat, 20 May 2017 18:52:03 +0100
Subject: [PATCH 2/2] Hide no-op service worker from user

---
 packages/react-dev-utils/README.md            |  4 +++
 .../noopServiceWorkerMiddleware.js}           | 25 ++++++++++++++++++-
 packages/react-dev-utils/package.json         |  1 +
 .../config/webpackDevServer.config.js         |  7 ++++++
 4 files changed, 36 insertions(+), 1 deletion(-)
 rename packages/{react-scripts/template/public/service-worker.js => react-dev-utils/noopServiceWorkerMiddleware.js} (50%)

diff --git a/packages/react-dev-utils/README.md b/packages/react-dev-utils/README.md
index c63600b4428..5daa9f062b8 100644
--- a/packages/react-dev-utils/README.md
+++ b/packages/react-dev-utils/README.md
@@ -240,6 +240,10 @@ getProcessForPort(3000);
 
 On macOS, tries to find a known running editor process and opens the file in it. It can also be explicitly configured by `REACT_EDITOR`, `VISUAL`, or `EDITOR` environment variables. For example, you can put `REACT_EDITOR=atom` in your `.env.local` file, and Create React App will respect that.
 
+#### `noopServiceWorkerMiddleware(): ExpressMiddleware`
+
+Returns Express middleware that serves a `/service-worker.js` that resets any previously set service worker configuration. Useful for development.
+
 #### `openBrowser(url: string): boolean`
 
 Attempts to open the browser with a given URL.<br>
diff --git a/packages/react-scripts/template/public/service-worker.js b/packages/react-dev-utils/noopServiceWorkerMiddleware.js
similarity index 50%
rename from packages/react-scripts/template/public/service-worker.js
rename to packages/react-dev-utils/noopServiceWorkerMiddleware.js
index 9ec515ec5f9..b6cee735065 100644
--- a/packages/react-scripts/template/public/service-worker.js
+++ b/packages/react-dev-utils/noopServiceWorkerMiddleware.js
@@ -1,4 +1,20 @@
-// This service worker file is effectively a 'no-op' that will reset any
+/**
+ * Copyright (c) 2015-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+'use strict';
+
+module.exports = function createNoopServiceWorkerMiddleware() {
+  return function noopServiceWorkerMiddleware(req, res, next) {
+    if (req.url === '/service-worker.js') {
+      res.setHeader('Content-Type', 'text/javascript');
+      res.send(
+        `// This service worker file is effectively a 'no-op' that will reset any
 // previous service worker registered for the same host:port combination.
 // In the production build, this file is replaced with an actual service worker
 // file that will precache your site's local assets.
@@ -15,3 +31,10 @@ self.addEventListener('activate', () => {
     }
   });
 });
+`
+      );
+    } else {
+      next();
+    }
+  };
+};
diff --git a/packages/react-dev-utils/package.json b/packages/react-dev-utils/package.json
index b5d5c127085..fa85d756de1 100644
--- a/packages/react-dev-utils/package.json
+++ b/packages/react-dev-utils/package.json
@@ -21,6 +21,7 @@
     "getProcessForPort.js",
     "InterpolateHtmlPlugin.js",
     "launchEditor.js",
+    "noopServiceWorkerMiddleware.js",
     "ModuleScopePlugin.js",
     "openBrowser.js",
     "openChrome.applescript",
diff --git a/packages/react-scripts/config/webpackDevServer.config.js b/packages/react-scripts/config/webpackDevServer.config.js
index 8d7eb0f1b5e..9c12de0af35 100644
--- a/packages/react-scripts/config/webpackDevServer.config.js
+++ b/packages/react-scripts/config/webpackDevServer.config.js
@@ -11,6 +11,7 @@
 'use strict';
 
 const errorOverlayMiddleware = require('react-error-overlay/middleware');
+const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
 const config = require('./webpack.config.dev');
 const paths = require('./paths');
 
@@ -72,6 +73,12 @@ module.exports = function(proxy, allowedHost) {
     setup(app) {
       // This lets us open files from the runtime error overlay.
       app.use(errorOverlayMiddleware());
+      // This service worker file is effectively a 'no-op' that will reset any
+      // previous service worker registered for the same host:port combination.
+      // We do this in development to avoid hitting the production cache if
+      // it used the same host and port.
+      // https://github.com/facebookincubator/create-react-app/issues/2272#issuecomment-302832432
+      app.use(noopServiceWorkerMiddleware());
     },
   };
 };