Thursday, August 4, 2016

Adding the In-Memory Web API to a SystemJS-based Angular CLI Application

8/6/2016 EDIT: On 8/2/2016, the Angular CLI was updated to reflect the fact that the CLI was being refactored to use Webpack instead of SystemJS.  Currently, an npm install of Angular CLI will still give you a version that uses SystemJS, and the following instructions apply to that SystemJS version.

As of version 1.0.0-beta.10, the Angular CLI tool does not provide an option for generating a base Angular 2 application that includes the in-memory web API, which is a tool that lets developers simulate the return of data from HTTP calls.  I figured adding the in-memory web API to my CLI-generated application was just a matter of mimicking how the HTTP lesson in the Tour of Heroes tutorial did it, but it was a bit more involved than that. Here's how you do it.

(From here on out, I'm going to abbreviate "in-memory web API" as IMWA for the sake of brevity. Someone needs to come up with a shorter, cooler name for this tool.)

First, you add the IMWA as a dependency in the package.json file:


"dependencies": {
  ...
  "angular2-in-memory-web-api": "0.0.14"
}

...and then run "npm install" from the command prompt in the directory containing the package.json file to download the IMWA node module (I tend to delete my entire "node_modules" folder first just to make sure everything installs fresh).

Then you add the neccessary imports to your main.ts file and use those imports in the bootstrap() method:


import { XHRBackend } from '@angular/http';

import { InMemoryBackendService, SEED_DATA } from 'angular2-in-memory-web-api';
import { InMemoryDataService }               from './app/in-memory-data.service';

import { HTTP_PROVIDERS } from '@angular/http';

...

bootstrap(AppComponent, [
  HTTP_PROVIDERS,
  { provide: XHRBackend, useClass: InMemoryBackendService },
  { provide: SEED_DATA, useClass: InMemoryDataService }      
]);

Then create a in-memory-data.service.ts file in your src/app directory with some temporary placeholder data:


export class InMemoryDataService {
  createDb() {
    let tempData = [
      {id: 1, name: 'foobar'}
    ];

    return { tempData };
  }
}

Up to this point, all of the setup is nearly the same as it was for the Tour of Heroes tutorial, but the final changes needed are CLI-specific.

When you use the CLI's "ng serve" command to compile and run the application on your local machine, the CLI generates a "dist" directory with all of the necessary files to execute the application. The "dist" directory consists of:

  • The index.html and global configuration files (main.js and system-config.js) in the root of the "dist" folder.
  • The "app" folder which contains the rest of the Angular 2 files specific to your application, from the main component file on down.
  • A "vendor" directory that contains the files from the various node modules needed to run the application, such as the core Angular 2 library files.

The IMWA needs to be included as a separate folder under that "vendor" directory in order for the IMWA to be available to your application.

The "angular-cli-build.js" file in the root of your project filespace (in the same directory as the package.json) controls which node modules make it into the build (the "dist" folder). Add the IMWA to the array of modules like so:


vendorNpmFiles: [
  ...
  'angular2-in-memory-web-api/*.+(js)'
]

The "*.+(js)" syntax ensures that all of the ".js" files in the IMWA node module are copied to the appropriate folder ("angular2-in-memory-web-api") under "vendor" (at this time, there are no ".js.map" files in the IMWA module).

Finally, you need to make sure the IMWA module in the "vendor" directory is loaded by SystemJS along with the regular Angular modules by adding the IMWA to the package configuration in the "system-config.ts" file in the "src" directory of your project:


/** Map relative paths to URLs. */
const map: any = {
  'angular2-in-memory-web-api': 'vendor/angular2-in-memory-web-api'
};

/** User packages configuration. */
const packages: any = {
  'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },
};

That should do the trick: run your app using "ng serve", open up the browser console, and confirm that there are no 404 error messages regarding the IMWA.

No comments:

Post a Comment