Created by: justingrant
This PR fixes #6044 (closed) and fixes #6296 (closed), which are sourcemap-related problems that make the VSCode debugger unable to debug code in node_modules
of CRA apps. "Unable to debug" means:
- breakpoints set on
node_modules
code trigger on different code lines than where the breakpoint was set - stepping into
node_modules
code will highlight the wrong line, and sometimes even the wrong module! - selecting a particular frame in a call stack will highlight the wrong line in a
node_modules
file
The cause of this problem was a Babel config change in #5096 from Sept 2018: https://github.com/facebook/create-react-app/blob/57ef103440c24e41b0d7dc82b7ad7fc1dc817eca/packages/react-scripts/config/webpack.config.js#L432-L436
The goal of that change was to force debuggers to show transpiled code instead of original source. Unfortunately, that's not what it did. Webpack still generates a sourcemap for node_modules
(to see it, open https://localhost:3000/static/js/0.chunk.js.map in any CRA app in dev mode), but this sourcemap doesn't match the code that Babel generated for each module. Notably there are differences in whitespace (extra blank lines) and comments between the sourcemap code in sourcesContent
and the original source. When VSCode tries to set a breakpoint or step into node_modules code, the sourcemap points to the wrong line in the webpack node_modules chunk.
BTW, this explains why the problem doesn't show up in the Chrome debugger, because the Chrome debugger only uses the inline sourcesContent
code in the sourcemap-- it ignores the actual source files on disk. VSCode, however, will try to load the original source files from disk using the sources
array in the sourcemap. This provides a better debugging experience-- for example, if you quit your debug session the same source files are still loaded, and you can set breakpoints before your app is running to debug startup behavior.
Anyway, this PR changes Babel config to ensure that Babel is correctly generating sourcemaps for node_modules code. Heads up: it will likely make build times longer, because the original change in #5096 made build times shorter.
To validate that the PR is working, use the following steps:
-
git clone https://github.com/justingrant/cra-sourcemap.git
- this repo is unaltered CRA boilerplate code. The only changes I made was to add VSCode config files to make it easier for VSCode newbies to get a debug session going to repro the problem and validate the fix. - Open VSCode
- Choose File->Add Folder to Workspace and choose the
cra-sourcemap
folder you cloned above - Open
src/index.js
in the IDE editor - Set a breakpoint on the call to
ReactDOM.Render
. If you don't know how to set a breakpoint in VSCode, one way to do it is to set the cursor on that line of code and press F9. yarn start
- Press F5 to start a debug session. It should start debugging immediately, but if you're asked, choose "Chrome" from the dropdown menu and then it will start.
- Now refresh the browser. This should trigger the breakpoint you set above.
- Click "Step Into", which is the down arrow on the debug toolbar. Or press F11.
- You'll now be in some webpack boostrap module-loading code that you'll need to get out of, so press Step Into (F11) a few more times until the editor returns to
index.js
. Now it's actually ready to call into React code. - Now click Step Into one more time.
Expected (after PR is applied):
IDE highlights the first line of createElementWithValidation()
, which is what ReactDOM.Render
resolves to inside React's original source code.
Actual (current behavior): A line of code is highlighted in the middle of a method-- it's clearly the wrong line.
BTW, to validate this PR I wrote a webpack plugin that compared the code in sourcesContent
of 0.chunk.js.map to the actual code sitting on disk. I ran it on my main project and got 870 of 1029 source files don't match the source map static/js/0.chunk.js.map
. Then I ran it against the PR configs and zero mismatches were reported.
Here's an excerpt from the plugin's output for current CRA configs, omitting the first 867 (!!!) mismatched files:
/Users/justingrant/Documents/hdev/h3/web/node_modules/webpack/buildin/global.js doesn't match sourcemap, starting at line 1, col 7
Original Line 1: var g;
Map Line 1: var g; // This works in non-strict mode
Original Line 2:
Map Line 2:
/Users/justingrant/Documents/hdev/h3/web/node_modules/webpack/buildin/module.js doesn't match sourcemap, starting at line 1, col 26
Original Line 1: module.exports = function(module) {
Map Line 1: module.exports = function (module) {
Original Line 2: if (!module.webpackPolyfill) {
Map Line 2: if (!module.webpackPolyfill) {
/Users/justingrant/Documents/hdev/h3/web/node_modules/zen-observable/lib/Observable.js doesn't match sourcemap, starting at line 7, col 33
Original Line 6:
Map Line 6:
Original Line 7: var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
Map Line 7: var _createClass = function () {
Original Line 8:
Map Line 8: function defineProperties(target, props) {
WARNING: 870 of 1029 source files don't match the source map static/js/0.chunk.js.map