Checklist for Building an Angular/Express App with Angular UI Router
Here are the things i try to remember whenever I’m creating a bare bones single-page Angular application with Express on the backend.
If you’ve ever needed to write an app really quickly for a hackathon or maybe a coding take-home for a job search, and you work with Angular, this post is for you. I’m not going to cover the intricacies of building an Angular and Express application. This is just a checklist of all the little pieces to remember to add. If you miss one of these, to quote XKCD, you will not go to space today.
What’s not included:
Just to be perfectly clear, this walkthrough only covers a basic Express application setup. You may notice I’ve not included some things that might seem basic or required. I may come back later and add them — but my goal was to walk through the things that are required for almost every single application you might have to throw together quickly. This checklist is built for someone who wants to show off their front-end skills (which is often a good idea for something like a hackathon, where you’ll be presenting a final product, not your actual code-base). For this reason, I’ve excluded some features from this checklist, the most notable of which are:
- Authentication: Not all apps require authentication. And those that do have very different requirements — some require local authentication with salted passwords, some require setting up OAuth with various providers (but which ones? Google? Facebook? Twitter?), some require setting up OAuth on your own API, etc etc etc. As such, I have not gone into authentication below. If you’d like to add authentication into your app, I recommend checking out Passport.
- Database: You might think it strange that there’s no database! But if you’re building an app for a take-home or hackathon, you might not need that kind of backend logic. You might just want a facade front-end that you can develop. Also, which Database would you want to use? SQL? MongoDB? I may later write some posts on full MEAN and SEAN stack application setups. I didn’t want to dig into it with this post, for brevity.
What is included:
So what did I choose to include in this checklist? This checklist assumes you are attempting to:
- build a single-page Angular 1.x application on the front-end
- deliver a single index.html page using an Express app
- deliver an API from an Express app, which will be consumed by the Angular app
- deliver static files (CSS, JS, etc) from an Express app
Directory Structure
Before we get started, thought I’d share the file and directory structure. Feel free to create any of these files now, to get yourself started.
project
|
+-- main.js (Express app)
|
+-- index.html (HTML where your app will run)
|
+-- api (API routes for sending data to Angular front-end)
| |
| +-- index.js
|
+-- public (for static files, like JS and CSS)
| |
| +-- js
| | |
| | +-- script.js (the Angular app)
| |
| +-- css
| |
| +-- style.css
|
+-- node_modules (this one is created automatically below)
Dependencies: Node & NPM
You will need to have Node and NPM installed to make this app work.
To install dependencies, create a package.json using the npm init command at the top-level directory of your app.
You can follow along and npm install as we get to each step, or if you prefer to cover your bases now, you can just run the following npm install command:
npm install --save express body-parser angular angular-ui-router
Express Checklist
Time to build an express app!
1. Install Express
To get started, make sure you’ve run npm install — save express (unless you preinstalled all dependencies).
2. Create an Express App
In your main.js file, instantiate your express app with the following code:
var express = require('express');
var app = express();3. Add Body Parsing
Add your body parsing functionality. This will allowed you to parse JSON and form data from your app.
Ensure you’ve installed the body-parser npm package.
Then add body parsing middleware to your app, like so:
var bodyParser = require('body-parser'); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: false}));4. Add an API Router
You’re going to need to create an API router next. This will catch any requests to /api and send them to a separate router that will handle them.
To add the router to your Express app, use the following lines of code:
app.use('/api', require('./api'))Then create a folder named api. In that folder, create an index.js file, and add the following content:
var express = require('express');
var router = express.Router(); // handle requests, or send them to another subrouter
module.exports = router;
This index.js file will act as a sort of dispatcher for all API requests.
5. Add Static File Routing
For this app, you will at a bare minimum need to serve the static files for your Angular application. You may also want to serve CSS files, Bootstrap, Foundation, or other JS libraries and/or frameworks. (Though heads up, I recommend not using jQuery if you’re already using Angular — that’s a lot of JS to bring into your frontend)
To serve static files from your node_modules directory, where the Angular script was added, add the following code to your main.js file:
app.use(express.static(__dirname + "/node_modules"));
Make sure to use __dirname for any other static directories you want to serve. If you want to also serve a “public” directory, add this line to your main.js file as well:
app.use(express.static(__dirname + "/public"));
6. Serve the Index for All Other Requests
In order to actually serve the application, you’ll need to send your index.html on any other requests received. To do so, add the the following code to your main.js file:
app.get("*", function(req, res, next) { res.send(__dirname + `/index.html`); })7. Add Error Handling
Error Handling Middleware: Make Future You Happy.
Seriously, everything is better with error handling — I highly recommend ensuring you have some good error handling middleware right from the beginning, yes even for hackathon projects (actually, especially for hackathon projects — you’ll need that itme you might have lost to debugging).
To add Express error handling middleware, add the following code to your main.js file:
app.use(function(req, res, next, err) {
res.status(err.status || 500)
res.send(err.message || 'Internal Server Error');
});7. Listen on a Port
Select a port (in the example, I’ve used 8000), and add this line at the bottom of your main.js file:
app.listen(8000);
If you’re planning to deploy to a service, like Heroku, you can also do the following:
app.listen(ENV.port || 8000);
Angular Checklist
You Angular application will be in the public/js/script.js file.
1. Instantiate Angular App with UI Router
You’ll need to remember to create the actual app object that’ll be used throughout your Angular code.
var app = Angular.module('MyApp', ['ui.router']);Don’t forget to inject the UI Router!
2. Configure App Settings
You’re going to need to configure your app to:
- Fix the route prefixes (to avoid having “#” in every URL)
- Provide a route to which the app will default (in the case of an unrecognized URL)
This will all happen in app.config(function() {}).
To do this, you’ll need to inject the locationProvider and the urlRouterProvider.
Let’s do this:
app.config(function($locationProvider, $urlRouterProvider) {
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('/');
});index.html Checklist
In order for your Angular app to work correctly, you’ll need to remember a few key things to add into your index.html file.
1. Create an index.html File
I’ll start with a basic, valid HTML page with no content, like so:
<!DOCTYPE html>
<html>
<head>
<title>My Page</title>
</head>
<body>
</body>
</html>
From there, we’ll make sure to load in all the things necessary to make the Angular app functional. Many of these are mission critical — if your app feels like it should be working, but it’s not, definitely check that you’ve done all of these.
2. Load in Angular
Remember to load in Angular itself! It’s easy enough to forget. But we’ve set up a static route for it and everything, so let’s be sure to add it into the <head>, like so:
<script src="node_modules/angular/angular.min.js"></script>
NOTE: The exact route within your node_modules MIGHT change in a later Angular release. Please double check that this is the correct path.
3. Load in the UI Router
You’ll also have to remember to load in the Angular UI Router into the <head> like so:
<script src="node_modules/angular-ui-router/release/angular-ui-router.min.js"></script>
NOTE: The exact route within your node_modules MIGHT change in a later Angular UI Router release. Please double check that this is the correct path.
4. Load in Your Application
Again, easy to forget, super critical to not forget. Same as above, add to the <head> in your index like so:
<script src="js/script.js"></script>
5. Bootstrap the Angular App with the ng-app Directive
Do not forget to use ng-app so to bootstrap your Angular application. It must be somewhere in your HTML — specifically, in a node that is going to be the parent of all nodes that you want to have Angular functionality.
Can’t stress this one enough — if you forget this for some reason, absolutely none of your Angular code will work at all.
I usually like to add the ng-app to the <body>, like so:
<body ng-app="MyApp"> </body>
If you’re building a complex application that requires multiple Angular applications, you might end up loading in different ng-app attributes in different parts of your HTML.
You could also choose to add the ng-app directive to the <html> element.
6. Add a UI View for the Angular UI Router
You’re going to need to decide what aspects of your page will change when the Angular router changes states. Typically, common components like the navbar, footer, or maybe even sidebars might remain the same, and the “content” of the site will change.
You can either add the ui-view as an HTML element, like so:
<ui-view></ui-view>
Or you can add it as an attribute on an HTML element of your choice, like so:
<div ui-view></div>
This really is up to you, and depends on the structure of your app.
7. Add a Base URL
If you want UI router to work correctly in HTML5 mode, which we added earlier to our Angular files, we need to add a <base> element inside the <head> of our HTML, and set it to our base route (“/”).
<head>
<base href="/">
</head>
Appendix: Putting it All Together
In case you’d like to see the files in their completeness, they are as follows:
main.js
Here is the main.js containing the Express app:
var express = require('express');
var app = express();var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());app.use('/api', require('./api'));app.use(express.static(_dirname + "/node_modules"));
app.use(express.static(_dirname + "/public"));
app.get("*", function(req, res, next) {
res.send(_dirname + "/index.html");
});app.use(function(req, res, next, err) {
res.status(err.status || 500)
res.send(err.message || 'Internal Server Error');
});app.listen(ENV.port || 8000);
api/index.js
Here is the api/index.js file:
var express = require('express');
var router = express.Router();// handle API requests
module.exports = router;
index.html
Here is the index.html file:
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
<script src="node_modules/angular/angular.min.js"></script>
<script src="node_modules/angular-ui-router/release/angular-ui-router.min.js"></script>
<script src="js/script.js"></script>
<link rel="stylesheet" href="css/style.css">
<base href="/">
</head>
<body ng-app="MyApp">
<ui-view></ui-view>
</body>
</html>
public/js/script.js
The Angular code in the script.js file will look like this:
var app = Angular.module('MyApp', ['ui-router']); app.config(function($locationProvider, $urlRouterProvider) {
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('/');
});Questions? Comments? Corrections? Please feel free to reach out to me and let me know! Email me!
Originally published at paloobi.tumblr.com.