Skip to content
This repository was archived by the owner on Apr 8, 2020. It is now read-only.

Debug with Angular Universal/prerenderer module #202

Closed
colltoaction opened this issue Jul 21, 2016 · 18 comments
Closed

Debug with Angular Universal/prerenderer module #202

colltoaction opened this issue Jul 21, 2016 · 18 comments

Comments

@colltoaction
Copy link

Hi!

I just started a new demo project using the Yeoman template with Angular2.

I have been having some trouble debugging when the prerenderer module is enabled. The main issue here is that we don't get any feedback from the server when there's an issue during prerendering i.e. in the console after running dotnet run.

I've had some moderate success when I made mistakes in my client side code by disabling this in the Home/Index.cshtml file:

<app
     asp-prerender-webpack-config="webpack.config.js">Loading...</app>
@*<app asp-prerender-module="ClientApp/boot-server"
     asp-prerender-webpack-config="webpack.config.js">Loading...</app>*@

But now I'm experiencing a new issue with the same behavior as I had with client side errors (page taking a long time to load followed by an error page), but if I disable prerendering it works fine.

I'm not asking to be helped in solving my particular issue: I'm sure it's a simple mistake I made because I'm new to Angular2. But I do want to know what to do to debug this, and suggest adding more information to the console output about the prerendering process. Maybe just outputting the javascript logs (e.g. console.log, console.error calls) would be enough.

Thanks!

@laskoviymishka
Copy link
Contributor

Well, basically any output from server should go directly to your console, so any console.log should work. In universal app i think it only possyble way to do this. You may also try to debug you node code, but it much more harder.

@colltoaction
Copy link
Author

The only clue I get is the following mesage: [Node] WARNING: your application is taking a long time to render the application and then System.Threading.Tasks.TaskCanceledException: A task was canceled.

How could I debug that?

@laskoviymishka
Copy link
Contributor

What is your setup for prerendering? Default options? Can you try to change protocol to Http from default sockets.

@colltoaction
Copy link
Author

I ran the yeoman aspnetcore-spa generator with Angular2 and I haven't touched the boot-server.ts file.

How can I change the protocol to default sockets? I looked around and googled it, but can't find anything.

@wizarrc
Copy link

wizarrc commented Jul 26, 2016

@tinchou I ran into the same issue myself when playing with nested routing. Turning off the SpaServices Prerendering tag helper did the trick. Also, alternatively removing all bindings on the nested template prevented it from timing out. My guess is it has something to do with the async timing of nested levels of component bindings. I wonder if pre-rendering is compatible in that scenario.

On a side note, it would be nice if I had a nice way of setting a break point in the code during node rendering since it is all compiled on the server during a refresh.

@SteveSandersonMS
Copy link
Member

SteveSandersonMS commented Jul 26, 2016

I've updated some parts of these libraries so that they support attaching a node-inspector debugger to the Node processes that they launch. This means you can debug through your TypeScript/JavaScript code when it's running on the server.

I'll add full docs for this later, but first, let's see if you can make it work based on these notes :)

Prerequisites

  1. Update your copy of the aspnet-webpack NPM module to the latest version (currently, 1.0.7):

    npm install --save aspnet-webpack
    
  2. Update your copies of the Microsoft.AspNetCore.NodeScriptServices / SpaServices / AngularServices packages to the latest version (currently, 1.0.0-beta-000008). To do this, edit your project.json file to set the correct version on any of those packages that are explicitly referenced. You are probably only referencing AngularServices directly, so edit your project.json to include:

    "Microsoft.AspNetCore.AngularServices": "1.0.0-beta-000008"
    

    ... and then, from your project root directory, run:

    dotnet restore
    

Enabling debugging

In your Startup.cs file, in the ConfigureServices method, add the following:

services.AddNodeServices(new NodeServicesOptions {
    LaunchWithDebugging = true
});

You probably also need to add using Microsoft.AspNetCore.NodeServices; at the top of the file too.

Make sure you're running everything in debug mode. For example, in your command line, set the ASPNETCORE_ENVIRONMENT environment variable to Development.

Now, run your application from that command line (e.g., dotnet run). Then in a browser visit one of your pages that causes server-side JS to execute.

In the console, you should see all the normal trace messages appear, plus among them will be:

  -----
  *** Node.js debugging is enabled ***
  Debugger listening on port 5858

  To debug, run:
     node-inspector

  If you haven't yet installed node-inspector, you can do so as follows:
     npm install -g node-inspector
  -----

In some other command line window, follow those instructions (i.e., install node-inspector as it describes, then run node-inspector). Then you can open a browser at http://127.0.0.1:8080/?port=5858 and you'll see the debugger UI.

By expanding the webpack:// entry in the sidebar, you'll be able to find your original TypeScript code (it's using source maps), and then set breakpoints in it. When you re-run your app in another browser window, your breakpoints will be hit, then you can debug the server-side execution just like you'd debug client-side execution. It looks like this:

screen shot 2016-07-26 at 18 56 12

(Note: although this looks like Chrome's native debugger for client-side code, it is actually a JavaScript-powered debugger UI that's connected to the server-side runtime)

Summary

As you can see, getting this to work is all quite delicate and fiddly. Maybe one day it might be possible to use VS Code as the debugging UI, but I'm not sure how far away that might be. If you hit any trouble getting this to work, please let me know!

@wizarrc
Copy link

wizarrc commented Jul 27, 2016

@SteveSandersonMS This looks amazing! Great Job! I tried it out for myself and I am running into problems with node.exe failing to initialize. Do you have any idea what might be happening?

fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[0]
An unhandled exception has occurred while executing the request
System.InvalidOperationException: The Node.js process failed to initialize: Debugger listening on [::]:5858

@SteveSandersonMS
Copy link
Member

Ah yes, I think I see what's wrong. It looks like Node behaves slightly differently in an IPv6 environment, which appears to be the case for you given the error message you got.

I've made a fix and published it as Microsoft.AspNetCore.NodeServices version 1.0.0-beta-000009. Could you try updating to that and see if it starts working?

@wizarrc
Copy link

wizarrc commented Jul 27, 2016

@SteveSandersonMS It works! And here I thought I didn't provide enough diagnostic information. I can confirm that I am in fact configured to use IPv6 with IPv4 as fallback. You should know that this solution only works when I open my chrome browser to the above address. When attempting to open in Edge, I receive the following error in my browser's console:

"Unknown experiment canvasInspection"

image

I assume this has something to do with EdgeHTML 13 not on feature parity with Chrome 52 (current versions as of now). What is this "canvasInspection" anyways? I guess a feature request is now in order to make node-inspector compatible with other browsers or to add this canvasInspection API to Edge. Any suggestions on the best route to enable node-inspector on the Edge browser?

@SteveSandersonMS
Copy link
Member

Any suggestions on the best route to enable node-inspector on the Edge browser

Contact the node-inspector project folks. But bear in mind that the debugger UI here probably comes from the Chrome project (since it's the same UI that ships in Chrome as the native JS debugger), and they might consider that to be the only important use case.

I'd suggest you just use Chrome for debugging with node-inspector!

@wizarrc
Copy link

wizarrc commented Jul 27, 2016

@SteveSandersonMS I thought that is what you would say. Bummer!

I found another two things that are causing me issues with node-inspector.

  1. After loading the page in chrome. The webpack:// tree is missing and in the console tab, it displays a message saying that .\TestSPA\ClientApp\webpack-output.js.map is missing. That's because webpack has it located at .\TestSPA\wwwroot\dist\main.js.map on disk. A simple workaround is to simply copy/paste/rename the map file to the location it is complaining about and reload. The webpack:// route shows up with all the .ts files intact as you demostrated.
  2. I don't know if this is a node inspector issue or not or can be solved on this end but I still haven't gotten breakpoints to work. Seems to be the chicken and egg problem. I need to load webpage to acquire js.map source, which loads the webpack://, so I can select my break points. However, I need to set my breakpoint before loading the webpage, because by then the loading of the page triggers the server rendering. I tried a page refresh with no success (probably because the server rendering is cached). I also tried changing my source code to trigger a recompile, but that seems to freeze up the whole system. I will keep hacking away at it. Don't know if anyone else has ran into that issue.

@colltoaction
Copy link
Author

It works great! It really helped me identify some issues in the backend. Looks good to close, but don't forget to document this somewhere!

@onethread
Copy link

onethread commented Aug 8, 2016

Works, but I get a lot of InvalidOperationException: The Node.js process failed to initialize: Error: listen EADDRINUSE :::5858 errors after hmr and rhmr do their thing. Any ideas? This is without anything attaching to 5858.

@SteveSandersonMS
Copy link
Member

EADDRINUSE errors just imply there's still some earlier Node process listening on the same port. You'll need to ensure all previous instances are properly stopped before you can start a new one. If you're on Linux/OS X (guessing you are from the phrasing of the message) then it might be enough just to run pkill node.

This is without anything attaching to 5858.

Are you really sure? Try sudo ps -A | grep node to confirm whether there really are any hidden instances still alive. If you're able to confirm there's really nothing listening on 5858 but still get this, are you able to supply any repro steps?

@onethread
Copy link

onethread commented Aug 16, 2016

Yeah I tried closing all node processes and starting over (I'm actually on windows btw):

  1. Launched a terminal window
  2. set the dotcore environment, then dotnet run
  3. Launch vscode and attach to process.

It works fine but after a few HMR/webpack rebuilding cycles, the error eventually manifests (and multiple node instances as well, 3 when originally there were 1).

@vbilici
Copy link

vbilici commented Sep 12, 2016

I am using windows and the same issue happens after code change and node restart when debugging enabled.

InvalidOperationException: The Node.js process failed to initialize: Error: listen EADDRINUSE :::5858

@SteveSandersonMS
Copy link
Member

Docs are now added here: https://github.com/aspnet/JavaScriptServices/tree/dev/src/Microsoft.AspNetCore.SpaServices#debugging-your-javascripttypescript-code-when-it-runs-on-the-server

@boban100janovski
Copy link

Just a quick note ... npm install -g node-inspector installation fails on Win10.
Solution is to point to a version ... this works : npm install -g node-inspector@0.7.4

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants