Developing
server-side apps with the popular Node.js framework can now be done with
the full support of Visual Studio IntelliSense, debugging, and project
management.
Node.js Tools for Visual Studio ( NTVS), is an open-source Visual
Studio plugin that transforms Visual Studio into a IDE for developing
Node.js apps. Node.js has become extremely popular, as a server-side
runtime environment for JavaScript apps; and this plugin brings the
possibility for Visual Studio users to take advantage of their knowledge
of the IDE to work with Node.js code. It includes IntelliSense, a
Node.js interactive window, debugging and profiling, among other
features. In this article, I provide an example of the usage of these
features.
Writing Node.js code in Visual Studio and Using IntelliSense
You can download the latest version of Node.js Tools for Visual Studio
here.
At the time of writing, the latest version for Visual Studio 2013 was
1.0 Release Candidate. It is very stable and allows you to use Visual
Studio 2013 as your IDE for Node.js projects without major problems. In
the event you've worked with the previous versions of the plugin, you
should upgrade because this release resolved many bugs and crashes. The
project is developed and supported by Microsoft and the community. It is
important to note that there is already a version that works with the
Visual Studio 2015 preview, so you can expect that the forthcoming
Visual Studio version will also allow you to use it as the IDE for
Node.js projects.
Node.js Tools works with your existing Node.js installation. In fact,
when you execute your Node.js project, the IDE will run the installed
node.exe. The Visual Studio debugger uses the node V8 debugger under the
hood, but you work with the IDE in the same way and with the same
windows you are used to interacting with when coding in C# or other
Visual Studio supported languages.
Once you install the tools, the New Project dialog box in Visual Studio provides the following new templates under
Installed | Templates | JavaScript | Node.js:
- Azure Cloud Service
- From Existing Node.js code
- Blank Node.js Console Application
- Blank Node.js Web Application
- Basic Node.js Express 3 Application
- Starter Node.js Express 3 Application
- Basic Node.js Express 4 Application
- Blank Azure Node.js Web Application
- Blank Azure Node.js Express 3 Application
- Starter Azure Node.js Express 3 Application
- Basic Azure Node.js Express 4 Application
Start a new project with the
Blank Node.js Web Application template. You can use IntelliSense to replace the code in
server.js
with the following lines. This code uses the HTTP and URL libraries to
create a very simple Node.js REST API that is capable of processing an
HTTP
GET status method with some parameters.
Listing One: Creating a simple REST API.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
var http = require("http");
var url = require('url');
var port = process.env.port || 1337;
var server = http.createServer(function (request, response) {
var parsedUrl = url.parse(request.url, true);
var query = parsedUrl.query;
if ((request.method == 'GET') && (parsedUrl.pathname == '/status')) {
status(query, response);
}
});
function status(query, response) {
var cameraToQuery = 0;
var detectedFacesCount = 0;
var globalStatus = 'N/A';
var lensStatus = 'N/A';
var environmentScore = 0;
if (query.position) {
switch (query.position) {
case 'front': cameraToQuery = 1;
globalStatus = 'OK';
lensStatus = 'OK';
environmentScore = 4;
detectedFacesCount = 300;
break;
case 'back': cameraToQuery = 2;
globalStatus = 'OK';
lensStatus = 'OK';
environmentScore = 3;
detectedFacesCount = 150;
break;
case 'left': cameraToQuery = 3;
globalStatus = 'OK';
lensStatus = 'OK';
environmentScore = 3;
detectedFacesCount = 200;
break;
case 'right': cameraToQuery = 4;
globalStatus = 'OK';
lensStatus = 'OK';
environmentScore = 2;
detectedFacesCount = 170;
break;
}
}
console.log("Requesting status information for camera #: " + cameraToQuery);
response.writeHead(200, {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "X-Requested-With"
});
var obj = {
cameraId: cameraToQuery,
globalStatus: globalStatus,
lensStatus: lensStatus,
environmentScore: environmentScore,
detectedFacesCount: detectedFacesCount,
};
response.write(JSON.stringify(obj));
response.end();
}
server.listen(port);
console.log("Server is listening at port " + port);
|
As you might expect from your experience with Visual Studio,
after you declare a variable, you can take advantage of IntelliSense to
check the available methods and properties. For example, after you
declare the
http variable on line 2, you can check the methods available for http by typing the dot (
.) after http in the following line (see Figure 1):
Figure 1: IntelliSense provides information about the available methods.
You will see the
createServer function in the displayed list. When you select
createServer, the IDE displays the documentation for the function. After you press
Enter to auto-complete the
http.createServer method and you open parenthesis to specify the arguments, the IDE displays the argument names list, in this case,
requestListener.
The code in Listing One uses the HTTP and URL libraries to create a
very simple Node.js REST API that is capable of processing an HTTP
GET status method with some parameters. The server listens on port 1337 or the port specified in
process.env.port. When the server receives an HTTP GET for the status method, it executes the
status function. This function checks whether a
position parameter value has been specified. The following are the four accepted values for
position:
front,
back,
left and
right. The code converts the specified position value to a camera id (
cameraToQuery)
and generates values to simulate status data provided by cameras that
detect and count faces in real-time. Then, the code sends the JSON
response with values for the following keys:
cameraId,
globalStatus,
lensStatus,
environmentScore, and
detectedFacesCount.
There are simpler ways to achieve the same goal by using other
Node.js libraries, such as Express. However, I want to keep the sample
code simple to allow you to understand the different features included
in Node.js Tools for Visual Studio.
Select
View | Other Windows | Node.js Interactive Window
and the IDE will display the Node.js REPL (short for Read-Eval-Print
Loop), which allows you to test code snippets. The interactive window
supports IntelliSense.
Debugging the Application with the Local Debugger
Right-click on the project name within Solution Explorer and the IDE
will display the General properties for the project where you can
configure the Node.exe path, arguments, and the debugger port, among
other properties. In this case, it isn't necessary to start a Web
browser when the app is launched, and so, you can uncheck the
Start web browser on launch checkbox.
You can set the desired breakpoints in the server.js file and launch
the Web application. By default, the tools use node's local V8-based
debugger. The debugging experience and the UI is exactly the same that
you already know from working with other supported Visual Studio
programming languages. Visual Studio connects to the node V8 debugger
over a socket, and so you can also debug Node.js remotely running on
another Windows computer or a different platform supported by Node.js.
For example, set a breakpoint at the first line of the status function:
var cameraToQuery = 0;
Then, start debugging the Web app. A node.exe window will appear and
this window will display the Node.js console output. The window will
display the following two lines (the port number might be different in
case you have a configured value for
process.env.port):
debugger listening on port 5858
Server is listening at port 1337
You can use a Web browser, Telerik
Fiddler, or the
curl utility to compose and send a
GET request to
localhost and the port in which the server is listening (
1337 or
process.env.port), adding
/status and one of the possible values for the
position parameter. For example, you can enter
http://localhost:1337/status?position=left in your Web browser or run the following curl command:
curl -X GET 'http://localhost:1337/status?position=left'
Visual Studio will hit the breakpoint at the first line of the
status
function. You can use the Autos, Locals, and Call Stack windows (see
Figure 2). You can also inspect variables and hover over either selected
expressions or valid identifiers to display a popup with the results of
their evaluation.
Figure 2: Using the Locals and Call Stack windows when debugging the Node.js Web app in Visual Studio.
This way, you can easily check that the
query argument has a
position property with a value equal to
left. You can step over each line of code and use the
Immediate Window to quickly evaluate expressions.
Once you finish executing the code in the
status function, you will see the following JSON response in the Web browser or as a result of the
curl command:
{"cameraId":3,"globalStatus":"OK","lensStatus":"OK","environmentScore":3,"detectedFacesCount":200}
Remember that the node.exe window displays the messages sent with
console.log, consequently, you will see a new line in this window:
Requesting status information for camera #: 3
In this case, I'm using a conventional breakpoint. You can also take
advantage of the advanced breakpoints. Go to the Breakpoints window and
right click on a breakpoint to see all the available options. For
example, the
Hit Count… option allows you to make the breakpoint hit when the location is reached and a specific hit count condition is satisfied.
You can also configure how Break on exceptions should work. You just need to select
Debug | Exceptions, expand
Node.js Exceptions and check all the
Thrown checkboxes for the different kinds of exceptions that you would like to make the debugger break when they are thrown.
You realize that
back isn't the appropriate position name for camera number 2, and therefore, you want to change it from
back to
rear. Enter
http://localhost:1337/status?position=rear in your Web browser or run the following curl command:
curl -X GET 'http://localhost:1337/status?position=rear'
The IDE will hit the previously set breakpoint again within the
status function. Luckily, the IDE supports edit and continue. Thus, you can replace the value in the case statement from
case 'back' to
case 'rear', save the changes and continue executing the code. Once you finish executing the code in the
status function, you will see the following JSON response in the Web browser or as a result of the
curl command:
{"cameraId":2,"globalStatus":"OK","lensStatus":"OK","environmentScore":3,"detectedFacesCount":150}
Installing npm Packages with the Integrated NPM UI
The previous example was a very simple Node.js REST API that uses two
standard libraries. However, in your real-life Node.js projects, you
will want to install additional npm packages and use them. You can run
npm from the Node.js Interactive Window (.npm) or the command line.
Visual Studio watches the file system and will update the project with
the additions.
However, the tools include an integrated NPM UI that enables you to
easily search and install npm packages without running commands. In case
you are running the project, stop its execution. Right-click on
npm
within the Solution Explorer and select Install new NPM packages…. A
dialog box allows you to search for the available npm packages.
You just need to enter some text from the package name and the list
will be updated with the package names and descriptions that match this
text. For example, enter
express and the dialog box will display all the packages that include
express in either the name or the description. Select
express 4.10.2
and notice that the right-hand side of the dialog box displays
additional information about the selected package (see Figure 3),
including its homepage. Then, click on Install Package. By default, the
options make NPM install the latest version of the selected package with
a standard dependency and automatically add it to
package.json.
Figure 3: Installing a new NPM package with the integrated NPM UI.
If you have experience working with Node.js, it is difficult to avoid working with
npm
in the command line. However, the UI might be helpful to easily search
for packages and check whether newer versions are available.
Node.js Tools for Visual Studio transforms Visual Studio into a very
good Windows IDE for Node.js projects. If you work with other
programming languages and are happy and productive using Visual Studio,
you will want to install this add-in to code Node.js projects there as
well.