Skip to content

Preparing Your Angular 1 Code For Angular 2 (Part 2)

This post is Part 2 of a series of blog posts where I’ll convert an Angular 1.x project to Angular 2. In Part 1, I upgraded the Angular client to use the latest guidelines in the John Papa Angular Style Guide.

Node.js has improved by leaps and bounds since I first wrote the Phone Cat MEAN project. If you’re not familiar, the tutorial on the AngularJS 1.x site takes you through the process of writing an application for viewing a catalog of cell phones and their details. Like many others, I did the tutorial when I was first learning Angular, but I took it further and turned it into an MEAN stack (Mongo, Express, Angular, Node) project.

Since that initial project, one of the biggest changes to Node has been support for ES6 (or, as it was renamed, ES2015). Using the latest ES6 syntax has the potential to simplify a lot of your code.

In this blog post, I’ll upgrade the Node.js server to use ES2015.

What do I need to write ES2015 in Node.js?

The latest versions of Node support many of the features of ES2015 natively. If you want to use an ES2015 feature that is not on that list, you can install Babel as a dependency to support additional features with on-the-fly transpilation in Node.

import and export are two of the features that Node doesn’t natively support. To support these features, I used npm to install and save babel-register and babel-preset-es2015. Then I required babel-register in my Node.js project and configured my .babelrc file to use the es2015 preset.

What ES2015 features work best in Node.js?

The ES2015 (ES6) features that I used in this project were:

  • import – the ES2015 version of the require() statement that every Node programmer is familiar with. It allows you to import all or portions of another file.
  • export – the ES2015 version of the module.exports command. Files can now have multiple exports and default exports
  • Arrow functions – a simpler way to create anonymous functions that have the same lexical this as the outer scope. That means you don’t have to wrap this to call it from within the anonymous function.
  • Promises – reduce the headaches of callback hell
  • let – block scoped variables
  • `${Template} strings` – interpreted strings that reduce the need for string concatenation

I’ve seen examples where people used Class but I didn’t think this project warranted it.

What were the steps to upgrade the code to ES2015?

  1. Use NPM to install the following dependencies:
    • babel
    • babel-preset-es2015
    • babel-register
    • body-parser
    • compression
    • express
    • mongoose
    • serve-static
    • morgan – dev only
    • nodemon – dev only
  2. Create a .babelrc file and set the preset to es2015
  3. Create a new Heroku app and attach MongoLab
    • In your Heroku app, open Settings -> Config Variables and reveal the variables
    • You should see a variable called MONGOLAB_URI
    • This variable holds your MongoLab username, password & URL in the format of mongodb://<username>:<password>@<sub-domain>.mongolab.com:<port>/<database>
    • You can use this connection string to connect to the MongoLab database, if you are running your Node server on your local computer. BUT make sure you do not commit this string to your GitHub repo. Committing this string to your repo makes it public and people have been known to steal passwords this way.
    • Rather than use this string directly in your code, it’s recommended that you use it as an environment variable in your code, as I have done (see db -> index.js). Then you can run your program from the command line like this:
      $ MONGOLAB_URI=<connection string> node index.js

      Since Heroku already has this variable set up, it will run your Node.js server correctly, if you use the environment variables in your code.

  4. Install the Heroku Toolbelt and use it on the command line to connect the git directory to Heroku
  5. Use the MongoLab interface or MongoDB’s CLI to add data to MongoDB
    • The inserted data was originally in the JSON files in the app -> phones directory
  6. Update the server code using this Git Repo as an example
    • I used that repo as an example but rather than use the resource pattern shown there, I wrote my own endpoints using standard Express functions
    • I ended up with the following directory structure:
    • /
      -- index.js
      -- server/
      ---- index.js
      ---- api/
      ------ index.js
      ------ phone.js
      ------ phones.js
      ---- db/
      ------ index.js
      ---- models/
      ------ phone.js
      ------ phones.js
      ---- static/
      ------ index.js
      
  7. Update the client to use $resource and connect it to the updated server
  8. Deploy the code to Heroku

How does ES2015 improve NodeJS code?

The full project is too long to walk through in this post but an example should suffice:

import { Router } from 'express';
import Phones from '../models/phones';
 
let router = Router();
 
router
    .get('/', (req, res) => {
        Phones
            .find({})
            .then(phones => res.json(phones))
            .catch(err => res.send(err));
    });
 
export default router;

In this example, I’ve used a number of the ES2015 (ES6) features. I’m using import to import the Router portion of the Express library and the default portion of the Phones model. At the bottom of the file, I export the router object as the default so that it can be imported into the API.

In the .get(), I’m using several Arrow functions as a substitute for the more verbose anonymous functions. The change in the lexical this wasn’t necessary, but the shorter code is appreciated.

The Phones model was written with the Mongoose library. Mongoose allows you to attach ES2015 promises. Here, I’m using the promise to handle the success and failure results with nice, tight Arrow functions.

The final code is available here. You can see a working copy of the website here.

Keep checking back for additions to this blog series. In upcoming posts, I’ll be taking a look at ng-forward, ng-upgrade and Angular 2.

Leave a Comment