As I mentioned before, the Angular CLI has the ability to deploy to GitHub Pages. This is a great way to showcase the client side of the the application, but doesn’t offer anything for the server side. It also makes it a bit more difficult to work with the Angular CLI when the file structure doesn’t exactly line up with expected layout. That brings up to an important point – how do you structure the project?
Yet another consideration at this stage is the overall deployment strategy. There are definitely tools that provide the end to end solution – handling the client side and server side in one shot. Work on the Angular application, work on the server, click the magic button and everything works. The downside is that usually they suck a bit. Unless the developers behind the integration tool are super keeners, they struggle with keeping up to date, especially as time wears on and the initial enthusiasm behind the integration of the two technologies wanes. Relying on someone else for integration can easily come at the price of using the latest technology, or perhaps just having your hands tied when it comes to design or tooling decisions. A good example of this is the MEAN stack, available at mean.io – what if you want, for example, to use PostgreSQL instead of MongoDB? The project also seems to be a bit underwater in terms of organization, which is to be expected for fast moving technologies but also makes it hard to jump on board.
Given that I’ve chosen to work with Express for this first attempt, what’s the easiest way to serve an Angular application? The short answer is that I’m not really sure. I don’t know what the story is for deploying Node applications – when I look around, people talk about running
npm install on the server and that strikes me as crazy. I was going a bit nutty, thinking a deterministic deployment story was priority 1 for production code, thankfully Yarn stepped in and validated my concerns. I’ll look into it more, but in the interest of moving forward, I’ll make it up as I go. Sticking with the “generator” route, why not opt for the Express Generator? I don’t have much experience with it, so I figured it might be worth looking into. At least it gives a common starting point.
Setting up Express
$ yarn global add express-generator $ express --view=ejs --git min-auth-server $ cd min-auth-server && yarn
We’re only going to serve up the Angular UI, so we can remove the placeholder UI and routing things – we’ll be adding our own with Angular:
$ rm views/index.ejs $ rm routes/* $ rm public/stylesheets/style.css # Delete the associated routing from app.js - var index = require('./routes/index'); - var users = require('./routes/users'); ... - app.use('/', index); - app.use('/users', users);
You can also uncomment the
app.use(favicon... line, as Angular CLI provides a favicon out of the box. Better to have something than nothing! This is also a good time to save your work:
$ git add . $ git commit -m "Initial commit for server"
For a first pass at integration, we’ll do it in a brutish, manual fashion as a proof of concept
# Build Angular application $ ng build --prod --aot # Copy the now-built Angular artifacts into the server $ cp -a min-auth-client/dist/. min-auth-server/public/
Now we can actually get this application moving, ignoring that it would suck to have to do this every time we wanted to deploy the client to the server.
# In Windows: $ SET DEBUG=min-auth-server:* & yarn start # In Linux:
$ DEBUG=min-auth-server:* yarn start $ yarn start v0.18.1 $ node ./bin/www min-auth-server:server Listening on port 3000 +0ms
Now you should be able to visit localhost:3000 and see our Node JS server with Express serving up our Angular application! May not look like much right now, but we’re laying the foundations, and this is a crucial piece of integration.
Build Angular and serve with Express automatically
The current status of Node + Angular applications appears to have everything live in the same directory. My guess is that this is the path of least resistance, so that’s the way people start doing it. Perhaps overgeneralizing, but Node servers seem to be closer to the disposable realm than long lived enterprise projects, so perhaps people have yet to run into issues scaling, or just solve it in their own custom fashion. There are numerous examples online of, for example, people invoking
ng new and then creating an
app.js to serve the
dist folder, or renaming the
dist folder to
public and serving that. While this works and is easy, it also takes the two very separate and modular technologies and couples them right together. As the application grows, it becomes more and more difficult to differentiate between the development server, the production server, the Angular development server, and the Angular production artifacts, and the deployment process. I personally value a strong separation between the various concerns – developing the client is generally different than developing the server, which is likewise different than deploying the app. It’s much easier to understand what you’re deploying if you have both a logical and physical separation between the client and the server, which usually gives you a better chance of deploying only what you need.
Unless I find something that fits exactly the purpose, I imagine the easiest way forward will be to quickly whip up some “build” tooling. I’ll take a look around and see what I come up with…