Angular 2 / TypeScript / Visual Studio Code – Tutorial

  Angular, TypeScript, Visual Studio Code

Preparing the development environment

Extensions – tslint: Let’s now install some VSCode extensions. In the left vertical pane we find five icons. The bottom one is called ‘Extensions’. We select it and enter ‘tslint’ in the search field on top. Most likely there will be just one entry left in the list of extensions. We install the tslint extension and restart VS Code.

Extensions – Angular 2 Snippets: To quickly create the boilerplate code for our first Angular 2 app, we use the ‘Angular 2 Snippets’ extensions. We already know how to install extensions, so that should be a no brainer.

Extensions – npm: We also need NodeJS with its package manager ‘npm’. There is a convenient plugin for VSCode called ‘npm’. We enter ‘npm’ into the extension pane search field and select the proper plugin: ‘npm , npm commands for VSCode’. Currently, its at version 3.3.0.

Show installed extensions: In the Extensions pane we see a menu button on the top right. Clicking on it reveals a few menu entries, and one of them is ‘Show Installed Extensions’. We click it and check the list of installed extensions.

IDE Commands: We use <Shift>+<Ctrl>+p to access the command panel. The command panel will display matching commands as we type. This is the first significant difference to other IDE’s like, for example, WebStorm which provides corresponding UI dialogs for most settings, whereas in VS Code we need to type commands and settings names. Instead of presenting dialogs, VS Code opens editor panes for us to edit settings files directly. This is definitely not as convenient as dialogs. To make things worse, the search for matching entries seems to be language dependent. For example, entering ‘inst’ for install will show ‘Install’ when using an English VS Code, and ‘Einstellungen’ when using the German version.

Changing language: Visual Studio Code ships with 10 available display languages (locales). Press <Shift>+<Ctrl>+p to bring up the Command Palette then start typing “config” to filter and display the Configure Language command. Press <Enter> and a locale.json file is created with the default value set to your operating system language. You can use IntelliSense (<Ctrl>+Space) to select a different supported language locale. Save locale.json and restart VS Code to use the new display language.

Creating a project folder: By pressing <Ctrl>+` (<Ctrl>+ö for German users) we open a terminal pane in VSCode. Because  we didn’t open a project folder yet, the user’s home directory is currently set. We need to create a project folder, preferably in a general workspace folder. So we change into that and create our first project folder by entering:

C:> mkdir MyFirstAngular2Project

We continue by creating our project’s folder structure. Usually a much more elaborate structure would be applied, but for the purpose of this walkthrough it’s as simple as this:

C:> mkdir MyFirstAngular2Project\app

More directories will be created automatically by either VSCode or npm. Now we open the project’s root folder with VSCode. File -> Open folder -> <path-to>\MyFirstAngular2Project.

Index.html: Every web app project starts with the index.html file because it specifies any app bootloading code. In our case, we need the necessary Angular 2 libraries. See our initial basic Angular 2 app’s index.html file which was derived from the excellent Angular 2 Quickstart tutorial:

<html>
 <head>
   <title>Angular 2 QuickStart</title>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1">
   <link rel="stylesheet" href="styles.css">
   <!-- 1. Load libraries -->
   <!-- Polyfill(s) for older browsers -->
   <script src="node_modules/core-js/client/shim.min.js"></script>
   <script src="node_modules/zone.js/dist/zone.js"></script>
   <script src="node_modules/reflect-metadata/Reflect.js"></script>
   <script src="node_modules/systemjs/dist/system.src.js"></script>
   <!-- 2. Configure SystemJS -->
   <script src="systemjs.config.js"></script>
   <script>
     System.import('app').catch(function(err){ console.error(err); });
   </script>
 </head>
 <!-- 3. Display the application -->
 <body>
   <my-app>Loading...</my-app>
 </body>
</html>

A typical Angular 2 app includes some bootstrap code, and some configuration settings:

  • package.json identifies npm package dependencies for the project.
  • tsconfig.json defines how the TypeScript compiler generates JavaScript from the project’s files.
  • typings.json provides additional definition files for libraries that the TypeScript compiler doesn’t natively recognize.
  • systemjs.config.js provides information to a module loader about where to find application modules, and registers all the necessary packages. It also contains other packages that will be needed by later documentation examples.

Beginning with the last one, systemjs.config.js has a corresponding <script> element in index.html. We need to create this file in our project’s root folder:

/**
 * System configuration for Angular samples
 * Adjust as necessary for your application needs.
 */
(function (global) {
  System.config({
    paths: {
      // paths serve as alias
      'npm:': 'node_modules/'
    },
    // map tells the System loader where to look for things
    map: {
      // our app is within the app folder
      app: 'app',
      // angular bundles
      '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
      '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
      '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
      '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
      '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
      '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
      '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
      '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
      // other libraries
      'rxjs': 'npm:rxjs',
      'angular2-in-memory-web-api': 'npm:angular2-in-memory-web-api',
    },
    // packages tells the System loader how to load when no filename and/or no extension
    packages: {
      app: {
        main: './main.js',
        defaultExtension: 'js'
      },
      rxjs: {
        defaultExtension: 'js'
      },
      'angular2-in-memory-web-api': {
        main: './index.js',
        defaultExtension: 'js'
      }
    }
 });
})(this);

Creating a package.json file: Up to now we haven’t provided yet any of the libraries that were specified in index.html and systemjs.config.js. A very comfortable way to do this is to use the npm extension. Press <Shift>+<Ctrl>+p and enter ‘pack’ (for package). We are being asked a few questions, and we answer most of them by just hitting <enter>. At the end, we have an intitialized package.json file. What’s left to do is to fill it with the app’s dependency libraries. Therefore, we need to manually download the lilbraries and put a reference to them into package.json. Let’s do it in two chunks. First we load all Angular2 modules. In the terminal pane, enter:

npm install @angular/common @angular/compiler @angular/core @angular/forms @angular/http @angular/platform-browser @angular/platform-browser-dynamic @angular/router @angular/upgrade --save

We appended the --save switch in order for npm to conveniently add the modules to the dependency section in package.json for us. The second chunk:

npm install core-js reflect-metadata rxjs systemjs zone.js angular2-in-memory-web-api --save

After installing the program’s dependencies, we also need to download a few development dependencies and also add them to package.json. Adding these will greatly help us when caught in an endless loop of code changes and checking the result in a browser.

npm install concurrently lite-server typescript typings --save-dev

This time the modules are going into the devDependencies section of package.html. Although your package.json might look different, make sure you replace it with the following content:

{
 "name": "walkthrough",
 "version": "1.0.0",
 "scripts": {
   "start": "tsc && concurrently \"npm run tsc:w\" \"npm run lite\" ",
   "lite": "lite-server",
   "postinstall": "typings install",
   "tsc": "tsc",
   "tsc:w": "tsc -w",
   "typings": "typings"
 },
 "description": "",
 "main": "main.js",
 "author": "",
 "license": "ISC",
 "dependencies": {
   "@angular/common": "^2.0.2",
   "@angular/compiler": "^2.0.2",
   "@angular/core": "^2.0.2",
   "@angular/forms": "^2.0.2",
   "@angular/http": "^2.0.2",
   "@angular/platform-browser": "^2.0.2",
   "@angular/platform-browser-dynamic": "^2.0.2",
   "@angular/router": "^3.0.2",
   "@angular/upgrade": "^2.0.2",
   "angular2-in-memory-web-api": "0.0.21",
   "core-js": "^2.4.1",
   "reflect-metadata": "^0.1.8",
   "rxjs": "^5.0.0-beta.12",
   "systemjs": "^0.19.39",
   "zone.js": "^0.6.25"
 },
 "devDependencies": {
   "concurrently": "^3.1.0",
   "lite-server": "^2.2.2",
   "typescript": "^2.0.3",
   "typings": "^1.4.0"
 }
}

tsconfig.json: This file also goes into the project’s root folder:

{
 "compilerOptions": {
 "target": "es5",
 "module": "commonjs",
 "moduleResolution": "node",
 "sourceMap": true,
 "emitDecoratorMetadata": true,
 "experimentalDecorators": true,
 "removeComments": false,
 "noImplicitAny": false
 }
}

typings.json:

{
 "globalDependencies": {
 "core-js": "registry:dt/core-js#0.0.0+20160725163759",
 "jasmine": "registry:dt/jasmine#2.2.0+20160621224255",
 "node": "registry:dt/node#6.0.0+20160909174046"
 }
}

LEAVE A COMMENT