I'm streaming

Multiple Angular Builds for Blue-Green Deployments using .htaccess and AWS Elasticbeanstalk

Bugs happen all the time, Many times bugs are presented in a production environment where the same code seemed to work flawlessly in a test or staging environment. Over the years of writing code that blows up in a production environment, I’ve come to realize the increasing need of a blue-green deployment strategy. The benefit of doing a Blue-Green deployment is that you can cycle servers between any environment ( swapping based on our url schema ) with the same code but build for different environments.

A quick explanation of how this works is that there are two ( or three in my case ). I use a node script to build to a dist folder and prepare that folder for distribution. I use an AWS CodePipeline and CodeBuild process to deploy to an ElasticBeanstalk environment. These urls contain the words ( dev, test as well as a naked url ). I usually follow the convention of (project-dev.hemstreet.io, project-test.hemstreet.io or project.hemstreet.io ).

.htaccess inside the root directory ( or where we run our script that runs the deploy )

RewriteEngine on
Options +FollowSymLinks

# Prod regex is greedy on purpose, rewrite the variable if we detect other environments in the url
SetEnvIf HOST ^.*$ PROJECT_BASE=prod
SetEnvIf HOST (test) PROJECT_BASE=test
SetEnvIf HOST (dev) PROJECT_BASE=dev

# status of !200 to stop from internal redirecting
# this will catch any resource that is not an asset and redirect to the index.html
# [L] Rule at the end will stop htaccess from going any further
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteRule ^(?!.*(js|css|svg|tff|woff|woff2|png)).* /%{ENV:PROJECT_BASE}/index.html [L]

# status of !200 to stop from internal redirecting
# We didn't match on an asset we are trying to load. It's safe to assume it's a valid angular route
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteRule ^(.*)$ /%{ENV:PROJECT_BASE}/$1 [L,QSA]

Now that we have our htaccess in place to rewrite urls based on the domain, we need to add our angular build script.


#!/usr/bin/env node
const shell = require('shelljs');
const fs = require('fs');

const dir = './dist';

console.time('Total Build Time');

// Make dist directory if it does not exist already
if (!fs.existsSync(dir)){

const environments = ['dev', 'test', 'prod'];

environments.forEach(env => {

  let buildOptions = [`--output-path=dist/${env}`, `--env=${env}`, `--aot`];

  if(env !== 'dev') {
  } else {

  // Speed up the build process but
  if(env !=='prod') {

  let commandToRun = `ng build ${buildOptions.join(' ')}`;
  console.log(`\n\nBuilding: dist/${env}`);
  console.log(`Running ${commandToRun}\n\n`);

  let cmd = commandToRun;
  if (shell.exec(cmd).code !== 0) {
    console.log(`\n\n Build time for ${env}`);

console.log(`\nMoving Htaccess File`);
let moveHtaccessCmd = `cp .htaccess ./dist`;
if (shell.exec(moveHtaccessCmd).code !== 0) {

console.timeEnd('Total Build Time');


Local Debugging

Install MAMP and point it’s base directory to your generated dist folder.

In the command line type the following and view the logs as they happen

tail -f /Applications/MAMP/logs/apache_error.log

Debugging on ElasticBeanstalk

run eb ssh

If you have not configured your cli yet, it will have you do a few configuration steps. Once you are ssh’ed into the machine you can navigate to /var/www/html. Inside that folder you will see our three folders with an .htaccess file. We can edit this with sudo and see our changed without having to deploy again.

An inventive, entrepreneurial and positively unsatisfied mind that constantly pushes the tech boundaries to create new solutions and devices that change people’s lives.

Leave a Reply