From 2ed8eccf0856c10cea9f84dd78029ba871aaf436 Mon Sep 17 00:00:00 2001
From: Jason Laster <jason.laster.11@gmail.com>
Date: Thu, 20 Sep 2018 18:54:50 -0400
Subject: [PATCH] Switch to eval-source-map (#4930)

---
 .../evalSourceMapMiddleware.js                | 45 +++++++++++++++++++
 packages/react-dev-utils/package.json         |  1 +
 .../react-error-overlay/src/utils/mapper.js   |  6 ++-
 .../config/webpack.config.dev.js              |  2 +-
 .../config/webpackDevServer.config.js         |  6 ++-
 5 files changed, 57 insertions(+), 3 deletions(-)
 create mode 100644 packages/react-dev-utils/evalSourceMapMiddleware.js

diff --git a/packages/react-dev-utils/evalSourceMapMiddleware.js b/packages/react-dev-utils/evalSourceMapMiddleware.js
new file mode 100644
index 000000000..dee6370f8
--- /dev/null
+++ b/packages/react-dev-utils/evalSourceMapMiddleware.js
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2015-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+'use strict';
+
+function base64SourceMap(source) {
+  const base64 = Buffer.from(JSON.stringify(source.map()), 'utf8').toString(
+    'base64'
+  );
+  return `data:application/json;charset=utf-8;base64,${base64}`;
+}
+
+function getSourceById(server, id) {
+  const module = server._stats.compilation.modules.find(m => m.id == id);
+  return module.originalSource();
+}
+
+/*
+ * Middleware responsible for retrieving a generated source
+ * Receives a webpack internal url: "webpack-internal:///<module-id>"
+ * Returns a generated source: "<source-text><sourceMappingURL><sourceURL>"
+ *
+ * Based on EvalSourceMapDevToolModuleTemplatePlugin.js
+ */
+module.exports = function createEvalSourceMapMiddleware(server) {
+  return function handleWebpackInternalMiddleware(req, res, next) {
+    if (req.url.startsWith('/__get-internal-source')) {
+      const fileName = req.query.fileName;
+      const id = fileName.match(/webpack-internal:\/\/\/(.+)/)[1];
+      if (!id || !server._stats) {
+        next();
+      }
+
+      const source = getSourceById(server, id);
+      const sourceMapURL = `//# sourceMappingURL=${base64SourceMap(source)}`;
+      const sourceURL = `//# sourceURL=webpack-internal:///${module.id}`;
+      res.end(`${source.source()}\n${sourceMapURL}\n${sourceURL}`);
+    } else {
+      next();
+    }
+  };
+};
diff --git a/packages/react-dev-utils/package.json b/packages/react-dev-utils/package.json
index 23ff82d5c..74093b4a6 100644
--- a/packages/react-dev-utils/package.json
+++ b/packages/react-dev-utils/package.json
@@ -17,6 +17,7 @@
     "crossSpawn.js",
     "errorOverlayMiddleware.js",
     "eslintFormatter.js",
+    "evalSourceMapMiddleware.js",
     "FileSizeReporter.js",
     "formatWebpackMessages.js",
     "getCSSModuleLocalIdent.js",
diff --git a/packages/react-error-overlay/src/utils/mapper.js b/packages/react-error-overlay/src/utils/mapper.js
index 92407be53..95aa006a2 100644
--- a/packages/react-error-overlay/src/utils/mapper.js
+++ b/packages/react-error-overlay/src/utils/mapper.js
@@ -34,7 +34,11 @@ async function map(
   });
   await settle(
     files.map(async fileName => {
-      const fileSource = await fetch(fileName).then(r => r.text());
+      const fetchUrl = fileName.startsWith('webpack-internal:')
+        ? `/__get-internal-source?fileName=${encodeURIComponent(fileName)}`
+        : fileName;
+
+      const fileSource = await fetch(fetchUrl).then(r => r.text());
       const map = await getSourceMap(fileName, fileSource);
       cache[fileName] = { fileSource, map };
     })
diff --git a/packages/react-scripts/config/webpack.config.dev.js b/packages/react-scripts/config/webpack.config.dev.js
index e967bb948..12b8f8cf2 100644
--- a/packages/react-scripts/config/webpack.config.dev.js
+++ b/packages/react-scripts/config/webpack.config.dev.js
@@ -76,7 +76,7 @@ module.exports = {
   mode: 'development',
   // You may want 'eval' instead if you prefer to see the compiled output in DevTools.
   // See the discussion in https://github.com/facebook/create-react-app/issues/343
-  devtool: 'cheap-module-source-map',
+  devtool: 'eval-source-map',
   // These are the "entry points" to our application.
   // This means they will be the "root" imports that are included in JS bundle.
   // The first two entry points enable "hot" CSS and auto-refreshes for JS.
diff --git a/packages/react-scripts/config/webpackDevServer.config.js b/packages/react-scripts/config/webpackDevServer.config.js
index 17dac9dc0..b5eb9349a 100644
--- a/packages/react-scripts/config/webpackDevServer.config.js
+++ b/packages/react-scripts/config/webpackDevServer.config.js
@@ -9,6 +9,7 @@
 'use strict';
 
 const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware');
+const evalSourceMapMiddleware = require('react-dev-utils/evalSourceMapMiddleware');
 const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
 const ignoredFiles = require('react-dev-utils/ignoredFiles');
 const config = require('./webpack.config.dev');
@@ -89,7 +90,10 @@ module.exports = function(proxy, allowedHost) {
     },
     public: allowedHost,
     proxy,
-    before(app) {
+    before(app, server) {
+      // This lets us fetch source contents from webpack for the error overlay
+      app.use(evalSourceMapMiddleware(server));
+
       // 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
-- 
GitLab