Setting up the Environment for Node.js and TypeScript

Currently I’m working on the book chapter explaining how Angular 2 communicates with the servers. An easy approach would be to use for the data feed a public RESTful API of one of servers (Youtube or something), but I wanted to have my own locally installed server.

Using one of the Java servers would be an easiest choice for me, but this would limit the readership to only those who know Java. Can’t do. Let’s stick to JavaScript. Opps, I meant to say TypeScript. Actually what I really meant was using Node.js on the server with the TypeScript.

Disclaimer: I’ve been using Node as a runtime for a while, but I’m very new to developing with Node.js framework.

After this disclaimer about 50% of the readers should have abandoned this page. Since you’re not one of them, let’s learn together how to start using the Node framework with TypeScript.


Creating a Web Server with Node and TypeScript

Node.js (a.k.a. Node) allows you to create standalone applications in JavaScript. Node does a great job in the area of communications using HTTP or WebSockets, so let’s start with creating a simple Web server.

I assume that you already have both Node and TypeScript compiler installed on your computer, otherwise do it now.

We’ll start with creating a standalone Node application implementing the server-side tier of our mini project. In this blog we’re no going to write the Angular client, but if we would our project’s directory could have the following structure:

ch8_project_structure

To stay IDE-agnostic lets open a command prompt and create a directory named http_sample with the subdirectory server and configure a new Node project there by running the following command:

npm init -y

This will create a small npm configuration file package.json with default settings. Now let’s create a file hello_server.ts with the following content:

import * as http from 'http'; // 1

const server = http.createServer((request, response)=> {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('Hello World!\n');
});

const port = 8000;

server.listen(port); // 2
console.log('Listening on http://localhost:' + port);

1. This code loads the Node’s module using the ES6 syntax “import * as” supported by TypeScript as well. Note that we use const instead of var here.

2. The listen() function is what makes this program run infinitely. Every client’s request will get a response with HTTP code 200 and the text Hello World!

The above code need to be transpiled and we’ll create the file tsconfig.json in the project directory to configure the tsc compiler:

{
 "version": "1.7.5",
 "compilerOptions": {
 "target": "es5",
 "module": "commonjs", // 1
 "emitDecoratorMetadata": true,
 "experimentalDecorators": true,
 "outDir": "build" // 2
},
"exclude": [
   "node_modules", // 3
   "client" // 4
 ]
}

1. This will instruct the TypeScript compiler tsc to transpile modules according to the CommonJS spec. In our example the transpiler will convert the import statement

import * as http from 'http';

into this:

var http = require('http');

2. The transpiler will put the .js files into the directory build

3. Don’t transpile code located in the directory node_modules that contains the project dependencies

4. When you create the directory client for the Angular (or other) app, but we don’t want to transpile the client’s code because the SystemJS loader will do it on the fly.

NOTE: If you decide to copy the content of tsconfig from the listing above, remove the comments as they are not supported in JSON format. I used them here only to provide the code notes with explanations.

After running the tsc command the transpiled file hello_server.js will be saved in the build directory and we can start our Web server:

node build/hello_server.js

Node starts the JavaScript engine V8, which in turn will run the script from hello-server.js, which creates a Web server and prints a message “Listening on http://localhost: 8000”. Open your browser at this URL, and you’ll see a Web page with the text Hello World!

Creating a Web Server to Serve JSON Data

Now let’s teach our Node Web server to serve JSON data. To send JSON to the browser you need to modify the header to specify the MIME type to be application/json. The following code snippet shows what it takes to send a JSON object:

const server = http.createServer((request, response) => {
response.writeHead(200, {'Content-Type': 'application/json'});
response.end('{"message": "Hello Json!"}\n');});

While the above code sample suffices as an illustration of how to send a JSON data, real-world applications require more functionality on the server side, e.g. reading files, routing based on the provided path, handling various HTTP requests based on the method (GET, POST et al). For our auction example, we’ll need to respond with either products or reviews data based on the request.

To minimize manual coding we’ll install Express, which is a Node framework. I won’t be using all of the functionality of Express for a simple reason: I don’t know Express. Actually, I should have said, “I’m not an Express expert”, but let’s be honest here. Express will help with creating a RESTful Web service that will send the appropriate JSON file based on the client’s request.

To install Express we’ll run the following command from the project directory:

npm install express –save

This will download Express into the node_modules folder of our project and will update the dependencies section in package.json. To install Express type definition files in the typings directory run the following command:

npm install express

Now we can import Express into our application and start using its API. Let’s assume that we want to create a couple of endpoints to serve the product information and reviews. Below is the code of the file my-express-server.ts that shows how you can implement routing based on the URL for the HTTP method GET:

import * as express from 'express';
const app = express(); // 1

app.get('/', (req, res) => res.send('Hello from Express')); // 2
.
app.get('/products', (req, res) => res.send('Got a request for products')); // 2

app.get('/reviews', (req, res) => res.send('Got a request for reviews')); // 2

const server = app.listen(8000, "localhost", () => { // 3

   const {address, port} = server.address(); // 4
   console.log('Listening on http://localhost:' + port);
});

1. Create an object that denotes the Express application.

2. In the above example we’ve illustrated routing only for the GET requests using the method get(), but Express supports all methods required for handling HTTP requests and responses. You can find the declarations (with types) of all of them in the file express.d.ts.

3. Start listening on the port 8000 at the address localhost and execute the code provided in the fat arrow function.

4. We use the destructuring syntax to automatically extract the values of the properties address and port. In the ES5 syntax we’d need to write two lines instead of one:

var address = server.address().address;
var port = server.address().port;

If you transpile the code and start this server (node my-express-server.js), you’ll be able to request either products or services depending on which URL you enter as shown below.

ch8_express_routing

Live TypeScript Recompilation and Code Reload

Since we write our examples in TypeScript, we need to use tsc to transpile and deploy JavaScript in Node. The TypeScript compiler has the compilation option -w that runs tsc in the watch mode so whenever a TypeScript file changes it gets recompiled automatically. To set the auto-compilation mode for our code we’ll open a separate command window in the directory with the sources and run the following command:
tsc -w

When no files to compiled are specified, tsc will get the options for compilation from the file tsconfig.json. Now whenever you make a change in the TypeScript code and save the file it’ll generate the corresponding .js file. Accordingly, to start our Web server with Node you can use the following command:
node my-express-server.js

Live recompilation of the TypeScript code helps, but the Node server won’t automatically pick up code changes after it started. You’d need to manually restart the Node server to see your code changes in action unless you’ll use a handy utility Nodemon  that will monitor for any changes in your source and automatically restart your server and reload the code.

You can install Nodemon either globally or locally. For global install using the following command:
npm install -g nodemon

The following command will start our server in a monitoring mode:
nodemon my-express-server.js

If you want to get fancy, install Nodemon locally (npm install nodemon –save-dev) and introduce npm scripts in your package.json file:

 “scripts": {
 "start": "node my-express-server.js",
 "dev": "nodemon my-express-server.js"
 },
 "devDependencies": {
 "nodemon": "^1.8.1"
 }

Now you’ll be starting the server as npm run dev in the development mode (auto restart/reload) or npm start in production (no restart/reload).

9 thoughts on “Setting up the Environment for Node.js and TypeScript

  1. The fact that javascript is in every browser is making it more and more apparent that node is going to keep gaining momentum unless something like web assembly comes in the picture soon.

  2. Yakov, I think you missed one step in the middle of this article: “npm install tsd -g”, otherwise “tsd install express” won’t work. Is it mandatory to install Node to install/configure Angular[1] ? I think, useful, but not mandatory (for having Npm), correct? Also how to develop Angular[1] apps with TypeScript? Is there a good reference on that?

  3. I’m trying to follow this tutorial but when I run tsc I run in an error.
    Searching on google hasn’t helped yet.

    I have the directory layout as in the tutorial, and both package.json and tsconfig.json files with the same contents as in the tutorial.

    tsc version is 1.7.5; npm is 2.14.12 and node is 4.3.1

    The error goes :

    $ tsc
    /usr/lib/node_modules/typescript/lib/tsc.js:31084
    var jsonOptions = json[“compilerOptions”];
    ^

    TypeError: Cannot read property ‘compilerOptions’ of undefined
    at getCompilerOptions (/usr/lib/node_modules/typescript/lib/tsc.js:31084:35)
    at Object.parseJsonConfigFileContent (/usr/lib/node_modules/typescript/lib/tsc.js:31074:22)
    at parseConfigFile (/usr/lib/node_modules/typescript/lib/tsc.js:31351:40)
    at performCompilation (/usr/lib/node_modules/typescript/lib/tsc.js:31362:45)
    at Object.executeCommandLine (/usr/lib/node_modules/typescript/lib/tsc.js:31336:9)
    at Object. (/usr/lib/node_modules/typescript/lib/tsc.js:31635:4)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)

      1. The problem is the comments. I copied the tsconfig.json exactly as you wrote it in the tutorial, comments included, and it turns out that tsc can’t parse the json, this json is undefined. I subùitted a ticket on github because I think there should be a better error message for that.

Leave a comment