Skip to content
This repository was archived by the owner on Apr 8, 2020. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,6 @@ public abstract class OutOfProcessNodeInstance : INodeInstance
protected readonly ILogger OutputLogger;

private const string ConnectionEstablishedMessage = "[Microsoft.AspNetCore.NodeServices:Listening]";
private const string DebuggingStartedMessageFormat = @"-----
*** Node.js debugging is enabled ***
{0}

To debug, run:
node-inspector{1}

If you haven't yet installed node-inspector, you can do so as follows:
npm install -g node-inspector
-----";
private readonly TaskCompletionSource<object> _connectionIsReadySource = new TaskCompletionSource<object>();
private bool _disposed;
private readonly StringAsTempFile _entryPointScript;
Expand Down Expand Up @@ -215,8 +205,8 @@ protected abstract Task<T> InvokeExportAsync<T>(
/// <param name="projectPath">The root path of the project. This is used when locating Node.js modules relative to the project root.</param>
/// <param name="commandLineArguments">Command-line arguments to be passed to the Node.js process.</param>
/// <param name="environmentVars">Environment variables to be set on the Node.js process.</param>
/// <param name="launchWithDebugging">If true, passes a flag to the Node.js process telling it to accept V8 debugger connections.</param>
/// <param name="debuggingPort">If debugging is enabled, the Node.js process should listen for V8 debugger connections on this port.</param>
/// <param name="launchWithDebugging">If true, passes a flag to the Node.js process telling it to accept V8 Inspector connections.</param>
/// <param name="debuggingPort">If debugging is enabled, the Node.js process should listen for V8 Inspector connections on this port.</param>
/// <returns></returns>
protected virtual ProcessStartInfo PrepareNodeProcessStartInfo(
string entryPointFilename, string projectPath, string commandLineArguments,
Expand All @@ -226,7 +216,7 @@ protected virtual ProcessStartInfo PrepareNodeProcessStartInfo(
string debuggingArgs;
if (launchWithDebugging)
{
debuggingArgs = debuggingPort != default(int) ? $"--debug={debuggingPort} " : "--debug ";
debuggingArgs = debuggingPort != default(int) ? $"--inspect={debuggingPort} " : "--inspect ";
_nodeDebuggingPort = debuggingPort;
}
else
Expand Down Expand Up @@ -389,10 +379,13 @@ private void ConnectToInputOutputStreams()
{
if (evt.Data != null)
{
if (IsDebuggerListeningMessage(evt.Data))
if (IsDebuggerMessage(evt.Data))
{
var debugPortArg = _nodeDebuggingPort.HasValue ? $" --debug-port={_nodeDebuggingPort.Value}" : string.Empty;
OutputLogger.LogWarning(string.Format(DebuggingStartedMessageFormat, evt.Data, debugPortArg));
OutputLogger.LogWarning(evt.Data);
}
else if (IsWarning(evt.Data))
{
OutputLogger.LogWarning(evt.Data);
}
else if (!initializationIsCompleted)
{
Expand All @@ -411,9 +404,17 @@ private void ConnectToInputOutputStreams()
_nodeProcess.BeginErrorReadLine();
}

private static bool IsDebuggerListeningMessage(string message)
private static bool IsDebuggerMessage(string message)
{
return message.StartsWith("Debugger attached", StringComparison.OrdinalIgnoreCase) ||
message.StartsWith("Debugger listening ", StringComparison.OrdinalIgnoreCase) ||
message.StartsWith("To start debugging", StringComparison.OrdinalIgnoreCase) ||
message.Contains("chrome-devtools:");
}

private static bool IsWarning(string message)
{
return message.StartsWith("Debugger listening ", StringComparison.OrdinalIgnoreCase);
return message.StartsWith("Warning:", StringComparison.OrdinalIgnoreCase);
}

private FileSystemWatcher BeginFileWatcher(string rootDir)
Expand Down
31 changes: 15 additions & 16 deletions src/Microsoft.AspNetCore.SpaServices/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -771,36 +771,35 @@ Caveats:

## Debugging your JavaScript/TypeScript code when it runs on the server

When you're using NodeServices or the server-side prerendering feature included in the project templates in this repo, your JavaScript/TypeScript code will execute on the server in a background instance of Node.js. You can enable debugging on that Node.js instance. Here's how to do it.
When you're using NodeServices or the server-side prerendering feature included in the project templates in this repo, your JavaScript/TypeScript code will execute on the server in a background instance of Node.js. You can enable debugging via [V8 Inspector Integration](https://nodejs.org/api/debugger.html#debugger_v8_inspector_integration_for_node_js) on that Node.js instance. Here's how to do it.

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

```
services.AddNodeServices(options => {
options.LaunchWithDebugging = true;
options.DebuggingPort = 5858;
options.DebuggingPort = 9229;
});
```

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
-----
```
warn: Microsoft.AspNetCore.NodeServices[0]
Debugger listening on port 9229.
warn: Microsoft.AspNetCore.NodeServices[0]
Warning: This is an experimental feature and could change at any time.
warn: Microsoft.AspNetCore.NodeServices[0]
To start debugging, open the following URL in Chrome:
warn: Microsoft.AspNetCore.NodeServices[0]
chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:9229/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
```

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.
As per instructions open the URL in Chrome. Alternatively you can go to the `Sources` tab of the Dev Tools (at http://localhost:5000) and connect to the Node instance under `Threads` in the right sidebar.

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:
By expanding the `webpack://` entry in the sidebar, you'll be able to find your original source 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](https://cloud.githubusercontent.com/assets/1101362/17149317/a6f7d00c-5362-11e6-969c-4c3a9bbc33f7.png)
![screenshot from 2017-03-25 13-33-26](https://cloud.githubusercontent.com/assets/1596280/24324604/ab888a7e-115f-11e7-89d1-1586acf5e35c.png)

(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)