Angular CLI with Express Generator

Connecting an Express Generator project to an Angular CLI project to set up a MEAN Stack application

Posted by Sam Clough on July 6, 2017

Angular CLI is a popular tool for creating Angular projects. It claims to follow best practices, and takes care of a lot of configuration and boilerplate code, freeing you to work on the more interesting parts of your application. Express is an application framework for Node.js, and Express Generator is a tool for creating an Express application skeleton. The MEAN stack combines MongoDB, Express, Angular and Node.js to build single-page web applications.

A MEAN stack project requires a workflow that builds the Angular app and serves it using Express. This is often best achieved using webpack, which is fairly difficult to learn. Starting a new MEAN stack application I was interested in giving Angular CLI a go, but the thought of creating a new webpack configuration that would work with Angular CLI was off-putting. It occurred to me that an easier option might be to link up an Express Generator project with an Angular CLI project. After some experimenting I found nesting an Angular CLI project within an Express Generator project to be an acceptable solution.

Tools Required

There are a few npm packages that should be installed globally. Angular CLI and Express Generator are required. While not required I recommend nodemon for monitoring your Express app for changes and automatically reloading.

npm install -g @angular/cli express-generator nodemon

Creating the Project

After installing the necessary tools the next step is to create an Express app with Express Generator. I will call mine 'AngularExpress'.

express --view=hbs AngularExpress

Now navigate to the project directory.

cd AngularExpress

Then install the node modules.

npm install

Now it's time to create the Angular CLI project. As mentioned above the approach I chose for this was to nest it inside the Express project. I will name the Angular CLI project 'angular'.

ng new angular

You should now have a directory angular within the root of your Express project.

Connecting the Apps

To connect these two apps we only need to work with the app.js file in the root directory of the Express app (which is also the root directory for the entire project). Somewhere around line 23 of app.js you will see the line:

app.use(express.static(path.join(__dirname, 'public')));
Replace it with the following:

app.use(express.static(path.join(__dirname, 'angular/dist')));

You can delete everything below this line except for module.exports = app. In the place of the code you have just deleted you will need to add some code to ensure that if a user inputs an invalid path in the URL they will still be served the Angular App.

// catch 404 and send app
app.use(function(req, res, next) {
  res.sendFile(__dirname + '/angular/dist/index.html');
});

To keep your code clean it is worth removing any unused imports and files. None of the views are used with this configuration as the index file is served directly from the Angular CLI dist directory, so these may be removed. At this stage there are no routes being used either so the require statements importing the routes files may be removed. After doing this Your app.js file should now look like this:

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var index = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'angular/dist')));

// catch 404 and send app
app.use(function(req, res, next) {
  res.sendFile(__dirname + '/angular/dist/index.html');
});

module.exports = app;

The project is now set up. Fairly simple right? Now for how to use it...

Working with the Project

This is where this approach falls short compared with a good webpack configuration. Due to us now having separate package.json files for the Express app and the Angular app we will be doing a bit of switching back and forward between directories. It's a minor inconvenience, but using nodemon makes it easier, as does opening a separate terminal for each of the two root directories.

From the main project root run nodemon to start serving the app.

nodemon start

If you try to visit localhost:3000 now, you will see an error, as the Angular app doesn't exist yet. To build the Angular CLI app navigate to the angular directory (in a new terminal window so as not to disrupt nodemon) then run the command:

ng build --watch

You can now view your app at localhost:3000. You can work with this now as you would with any Angular CLI project. Likewise, your APIs can be written as normal in the Express project.

Conclusion

Linking an Express app created with Express Generator with an Angular CLI app can be done easily and quickly, taking only a few minutes. This approach maintains significant separation between the apps and is suitable for anyone unsure of whether they will continue to use Node.js for their back end or anyone wanting to make use of Angular CLI without diving deep into webpack and the Angular framework.