colinskow / angular-electron-dream-starter

:tada: An Angular Electron Starter kit featuring Webpack, Angular 4 (Router, Http, Forms, Services, ngrx, Tests, E2E, Coverage), Karma, Spectron, Jasmine, Istanbul, and TypeScript
MIT License
162 stars 54 forks source link

Debug with Visual Studio Code #1

Closed greg9504 closed 7 years ago

greg9504 commented 7 years ago

Just wondering what your development process is for using Visual Studio code to debug your Electron instance. Is it possible to use VS Code to debug the instance started with hot module replacement (npm run start)? I've tried to use a launch configuration to attach to the process ("request": "attach") but haven't been successful. I have been able to debug an instance started from VS Code ("request": "launch").
To do so I had to: edit /config/webpack.dev.js and change (line 53) devtool: 'cheap-module-source-map' to devtool: 'source-map' Build with: npm run build:dev

Then modify the included launch configuration slightly so the source maps were found:

      {
            "name": "Debug Dev Renderer Process",
            "type": "chrome",
            "request": "launch",
            "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd",
            "runtimeArgs": [
              "${workspaceRoot}/dist",
              "--enable-logging",
              "--remote-debugging-port=9222"
            ],
            "sourceMaps": true,     
            //"trace": "verbose",       
            "webRoot": "${workspaceRoot}"             
        }

The only change is webRoot was changed from:

"webRoot": "${workspaceRoot}/dist"

to

"webRoot": "${workspaceRoot}"

Note I ran a build:dev but started a debug against the "dist" directory. This seems counter intuitive.

With this approach I'm having to manually build to pick up any source changes (stop debugging, npm run build:dev, launch debug). If I do "npm run watch" my sources get auto built on a source change but if there is a debug instance running the debugger loses sync (break points no longer hit).

So I figured starting an instance with HMR would be the answer. But no luck doing so. Is my only debug option for HMR the embedded Chrome debugger?

Thanks. Greg.

NPM --version: 3.10.10 webpack 2.2.1 vscode-chrome-debug-core: 3.14.14

colinskow commented 7 years ago

I believe this is supposedly fixed in Webpack 2.3.2 https://github.com/webpack/webpack/issues/3579

Would you upgrade and see if it works?

greg9504 commented 7 years ago

Hello,

Thanks for the reply. I updated to Webpack 2.3.2 and reverted the changes. This seems to have fixed the problem with debugging and source maps, webpack.dev.js devtool: 'cheap-module-source-map' now produces usable source maps.

I did however have to use the changes above to the launch.json. Attached below.

My development process is: npm install (to update webpack) npm run build:dev npm run watch

Then debug with Visual Studio. I launch the application with VS Code using the launch config for renderer process. I'm able to debug and break points work. If I make a source change without stopping the app, the source compiles and I see the app reload in the Electron window. However Visual Studio Code now doesn't stop for any of my break points. I do see the console output in Code's debug console. So the link between the two appears to be intact. I'm just curious if this is supposed to work. I've been looking over the log generated by VS Code but so far nothing stands out.

Thanks Greg.

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug Main Process",
            "type": "node",
            "request": "launch",
            "cwd": "${workspaceRoot}/dist",
            //"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
            // Use the following for Windows
            "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd",
            "program": "${workspaceRoot}/dist/index.js",
            "outFiles": ["${workspaceRoot}/dist/**/*.js"]
        },
        {
            "name": "Debug Dev Renderer Process",
            "type": "chrome",
            "request": "launch",
            "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd",
            "runtimeArgs": [
              "${workspaceRoot}/dist",
              "--enable-logging",
              "--remote-debugging-port=9222"
            ],
            "sourceMaps": true,     
            "trace": "verbose",       
            "webRoot": "${workspaceRoot}"

        },
        {
           // haven't been able to get this to work.
            "name": "Attach to Chrome, with sourcemaps",
            "type": "chrome",
            "request": "attach",
            "url": "http://localhost:3000/*",
            "port": 9222,
            "sourceMaps": true,
            "trace": "verbose", 
            "webRoot": "${workspaceRoot}"
        }
    ]
}
colinskow commented 7 years ago

Hi Greg,

I honestly haven't tested debugging breakpoints in VSCode. The existing launch.json was copied from another Electron starter. Since HMR is injecting dynamic code I don't think that it will support breakpoints.

This project is forked from https://github.com/AngularClass/angular2-webpack-starter

I couldn't think of a use for having a non-HMR dev mode so I removed it, but breakpoint debug is a strong use case. If we remove HMR altogether and just use pure electron-connect will breakpoints work after refresh or do we have to relaunch Electron every single time?

If you can get this working and figure out the ideal debug workflow then I would very much welcome a pull request!

greg9504 commented 7 years ago

Hi, The workflow I mention above is working for me, I just restart debugging if I need to step into the code after a change. Unfortunately I am not familiar with electron-connect to know the answer.

If I find a better way I'll report back here. I lost a day today because the Debugger for Chrome extension for VS Code stopped working for Electron apps after an update to 3.0.0. I haven't tried the fix yet (usingRuntimeExecutable in launch config), but if you use 3.0.0 or above of the extension this is something to be aware of. https://github.com/Microsoft/vscode-chrome-debug/issues/407

colinskow commented 7 years ago

Try cloning the latest version of the repo. Everything should be working now (without your fix above.) I also upgraded to Angular 4.

1) npm run build:dev 2) Launch "Debug Renderer Process" from VSCode. 3) After each change npm run build:dev and launch again. Hot reloading won't work with debugger.

Feel free to re-open this if you still run into issues.

greg9504 commented 7 years ago

Thanks I'll give it a try. Did you see that the base repo is about to undergo a similar rebase for Angular 4 etc: https://github.com/AngularClass/angular2-webpack-starter/issues/1686

colinskow commented 7 years ago

Haha... I just gave them a jumpstart! https://github.com/AngularClass/angular2-webpack-starter/pull/1691

SlickNutter commented 7 years ago

@greg9504 Have you found a way to enable breakpoints in "Debug Main Process"?

greg9504 commented 7 years ago

@SlickNutter I swear I used to be able to do this. However I just tried it with the both 2.7.3 and 3.1.6 versions of the Debugger for Chrome extension for VS Code and I am unable to get it to work. I've opened a ticket with the extension authors... https://github.com/Microsoft/vscode-node-debug/issues/152 Read that over and tell me if you are seeing the same problem.

greg9504 commented 7 years ago

@SlickNutter as a work around, place the following line in your code where you want to break (rebuild, npm run build:dev) and use the Debug Main Process configuration from above . Single stepping works. debugger;

Oh and for clarification, when you are debugging the main process you are using the Node debugger, which is built into Visual Studio Code, not the Debugger for Chrome extension (which I had assumed originally). The Debugger for Chrome extension is only used when debugging the renderer process.

SlickNutter commented 7 years ago

@greg9504 This is the config I'm using in my launch.json and doesn't work:

{
     "name": "Debug Main Process",
     "type": "node",
     "request": "launch",
     "cwd": "${workspaceRoot}/dist",
     //"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
     // Use the following for Windows
      "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
      "windows": {
          "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd"
       },
       "program": "${workspaceRoot}/dist/index.js",
       "outFiles": ["${workspaceRoot}/dist/**/*.js"],
       "protocol": "inspector",
       // "sourceMaps": true,
       "args": [
           "."
        ],
        "restart": true
}
greg9504 commented 7 years ago

@SlickNutter you have the wrong protocol set. Either leave it out or set it to legacy.
Then on line 20 of src/electron/index.ts put : debugger; rebuild: npm run build:dev then debug. That should allow you to single step through but not set break points. When you do this you will see VS Code opens a new readonly instance of index.ts. The problem is with the webpack configuration that generates the source maps. This link explains why it is happening: https://code.visualstudio.com/docs/nodejs/nodejs-debugging#_javascript-source-map-tips

Basically for Node debugging VS Code does not support the webpack:/// prefix, which is how the map files are generated. I have managed to get breakpoints to work with the following:

Ideally you shouldn't have to edit the .map file and should be able to set the sourceRoot via webpack configuration. I have tried the following but this did not work, in /config/webpack.electron.js: line 85 under plugins:

new webpack.SourceMapDevToolPlugin({
        moduleFilenameTemplate:'[absolute-resource-path]',
        fallbackModuleFilenameTemplate:'[absolute-resource-path]?[hash]',
        filename: "[file].map",
        sourceRoot:"../"}
      )

Unfortunately that does not produce a valid map file. Still looking for the correct solution. What is happening in our case is that VS Code is looking for the source under /dist but we want it to look under root, that's why setting the sourceRoot:"../" in the map works. I'm going to try to update to the latest webpack and try a few more things. Although my understanding of webpack is pretty basic....

greg9504 commented 7 years ago

@SlickNutter OK I got this to work with the following modification to the output setting in webpack.electron.js:

output: {
      path: DEV_SERVER ? helpers.root('dev') : helpers.root('dist'),
      filename: '[name].js',
      sourceMapFilename: '[file].map',
      devtoolModuleFilenameTemplate: "..//[absolute-resource-path]",
      devtoolFallbackModuleFilenameTemplate: "..//[absolute-resource-path]?[hash]"
    },

Note the "..//" before the [absolute-resource-path].

and my launch config looks like:

{
            "name": "Debug Main Process",
            "type": "node",
            "request": "launch",
            "cwd": "${workspaceRoot}/dist",
            //"trace": true,
            "sourceMaps": true,
            "protocol": "legacy",             
            //"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
            // Use the following for Windows
            "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd",
            "outFiles": [
                "${workspaceRoot}/dist/**/*.js"
            ],
            "program": "${workspaceRoot}/dist/index.js"           
        },

Now you should be able to set breakpoints in /src/electron/index.ts had have VS Code break. Remember to rebuild after changing /config/webpack.electron.js