KevinM KevinM - 1 month ago 32
Node.js Question

Deploy Angular 2 app to Heroku

In the past I always bundled my Angular 1 and Rails apps together and typically used heroku, which has worked great for me. Now that I'm over to Angular 2 I want to separate out my Angular and Rails code. I've created a very basic Angular 2 app via the Angular-Cli, but I haven't been able to figure out how to deploy it to Heroku. I'm not using expressjs or anything like that. Anyone figure it out yet?

Answer

Ok I came up with a solution. I had to add a very basic PHP backend, but it's pretty harmless. Below is my process.

First setup a heroku app and Angular 2 app.

  1. Create your heroku app
  2. Set the heroku buildpack to heroku/php
    • heroku buildpacks:set heroku/php --app heroku-app-name
  3. Create a project via Angular-Cli
  4. Add a index.php file to /scr with the below snippet

    <?php include_once("index.html"); ?>

  5. Add a Procfile to /scr with the below snippet

    web: vendor/bin/heroku-php-apache2

  6. Added /deploy to the .gitignore

Now I used a npm package to push a tarballs to heroku

  1. Here's a simple package to upload the tarball, https://www.npmjs.com/package/heroku-deploy-tarball
    • npm i heroku-deploy-tarball --save
  2. I'm also using tar.gz to create the tarball
    • npm i tar.gz --save
  3. Then I created the deploy.js file at the root of my projecdt with the following code. I first run the buildCommand specified and then move the index.php and Profile to the dist folder. I then tarball the entire dist folder and it gets uploaded to heroku.

var deploy = require('heroku-deploy-tarball');
var targz = require('tar.gz');
var exec = require('child_process').exec;

var requestedTarget = process.argv[2];

if (!requestedTarget) {
  console.log('You must specify a deploy target');
  return;
}

var targets = {
  production: {
    app: 'heroku-app-name',
    tarball: 'deploy/build.tar.gz',
    buildCommand: 'ng build --prod'
  }
}

var moveCompressFiles = function (callback) {
  exec('cp ./src/index.php ./dist/index.php',
    function(err) {
      if(err)
        console.log(err);
      console.log('index.php was copied.');
    });
  exec('cp ./src/Procfile ./dist/Procfile',
    function(err) {
      if(err)
        console.log(err);
      console.log('Procfile was copied.');
    });

  new targz().compress('./dist', './deploy/build.tar.gz',
    function(err){
      if(err)
        console.log(err);
      else
        callback();
      console.log('The compression has ended!');
    });
};

console.log('Starting ' + targets[requestedTarget].buildCommand);
exec(targets[requestedTarget].buildCommand, {maxBuffer: 1024 * 500}, function(error) {
  if (!error) {
    console.log(targets[requestedTarget].buildCommand + ' successful!');
    moveCompressFiles(function () {
      deploy(targets[requestedTarget]);
    });
  } else {
    console.log(targets[requestedTarget].buildCommand + ' failed.', error);
  }
});
  1. Now just run node deploy production and it should deploy to heroku.

Edit

Just got word from heroku that they are working on an experimental buildpack that would allow for static sites like this. Here is the link to the build pack.