Deploying FastBoot apps with ember-cli-deploy

By: Michael Klein | March 1st, 2018

ember-cli-deploy is the best way to deploy your Ember.js applications because it's flexible and allows for a lot of customization in your deployment process.

You can learn more about this addon on its documentation page that goes into great detail of how ember-cli-deploy structures your deploys, how you can customize your deploys via deploy-plugins and what configuration options exist in config/deploy.js.

Until recently there wasn't an obvious way how to deploy FastBoot-apps with ember-cli-deploy though. In this blogpost I want to go into detail of what needs to be done to deploy your FastBoot-apps so that you don't need to come up with your own scripts outside the ember-cli-ecosystem to deploy your new applications or to abandon the way you are used to deploying your Ember.js-applications right now if you make the switch over to FastBoot.

Running FastBoot

There are different ways to run FastBoot and the official documentation page gives an overview of the different ways. To deploy your FastBoot-applications with ember-cli-deploy you will run FastBoot via the ember-fastboot-app-server-project. This is a very flexible (read customizable) approach to running FastBoot which lets you run a custom node.js-server that will serve your FastBoot app to your users. Overall ember-fastboot-app-server is a great project that makes it very easy to run your FastBoot applications. You can run your FastBoot-App-Server anywhere you would otherwise host node.js-applications. How to do this is obviously outside of the scope of this article but a very easy way to do this is to run your FastBoot-App-Server on a PaaS like Heroku.

Running your FastBoot-applications is only half the battle though. The interesting part is serving new versions of your application to your users as soon as you decide to deploy.

Notifiers and Downloaders

fastboot-app-server comes with the notion of notifiers and downloaders. This functionality makes sure that you don't have to take up the responsibility to upload a static-build of your application to your FastBoot-servers manually across all your servers each time you want to update your application. Instead you tell your fastboot-app-server's notifier to watch for updates of a manifest-file on a storage-system of your choosing (e.g. Amazon-S3) that contains a link to the active version of your application. As soon as you update the content of said manifest-file to point to a new version the fastboot-app-server's downloader will download the new application build hosted somewhere (e.g at the same storage system the manifest-file resides on) and restart, now serving the new version of your application.

That's a pretty long explanation for a very easy concept illustrated in the following picture where we have multiple fastboot-app-server-instances behind a load-balancer that serves our application to our users:

fastboot-app-server-min

So putting this all together a very basic fastboot-app-server-setup could look like this:

// server.js
const FastBootAppServer = require('fastboot-app-server');
const S3Downloader = require('fastboot-s3-downloader');
const S3Notifier = require('fastboot-s3-notifier');

let downloader = new S3Downloader({
  bucket: process.env.S3_BUCKET,
  key: 'fastboot-deploy-info.json'
});

let notifier = new S3Notifier({
  bucket: process.env.S3_BUCKET,
  key: 'fastboot-deploy-info.json'
});

let server = new FastBootAppServer({
  downloader,
  notifier,

  gzip: true,

  beforeMiddleware(app) {
    app.use((request, response, next) => {
      if (request.headers['x-forwarded-proto'] === 'https') {
        return next();
      } else {
        return response.redirect(301, `https://${request.hostname}${request.url}`);
      }
    });
  }
});

server.start();

Please note that we are using fastboot-deploy-info.json as the name for our manifest-file. This is the default for the deploy-plugins we will be using but can be customized. In addition to setting up the notifier and downloader this fastboot-app-server also makes sure to redirect non https-requests to https.

But how can we now finally make use of ember-cli-deploy to deploy our FastBoot-application? And how do the FastBoot-deploy-plugins actually work?

ember-cli-deploy FastBoot-Plugins

The available ember-cli-deploy FastBoot-plugins make use of the described notifier and downloader-interaction. There is one base plugin that takes care of creating a FastBootable application build (ember-cli-deploy-fastboot-app-server) and other more specific ones that will update the manifest-file when you activate a new revision of your application via the ember deploy:activate-command. Currently there is only one available that expects you to use Amazon-Web-Services for hosting your Ember.js application assets (ember-cli-deploy-fastboot-app-server-aws).

The deployment setup is illustrated in the following image. We initiate a deploy via the ember deploy-command and upload our application build artifacts (i.e. the zipped-up application build) to our storage system. When we want to serve a new version of our application to our users we can run the ember deploy:activate-command to update the manifest-file on our storage system and the fastboot-app-server will restart and serve our new application.

ember-cli-deploy-fastboot-app-server-min-2

These are the necessary deploy plugins that you need to install to make this work with your application:

// package.json
{
  // ...
  "devDependencies": {
    // ...
    "ember-cli-deploy": "^1.0.2",
    "ember-cli-deploy-build": "^1.1.1",
    "ember-cli-deploy-display-revisions": "^1.0.0",
    "ember-cli-deploy-fastboot-app-server": "^0.0.3",
    "ember-cli-deploy-fastboot-app-server-aws": "^0.0.3",
    "ember-cli-deploy-revision-data": "^1.0.0",
    "ember-cli-deploy-s3": "^1.1.0",
    // ...
  },
  // ...
}

We need ember-cli-deploy to get the deploy-command, ember-cli-deploy-build to build our application when deploying, ember-cli-deploy-revisions and ember-cli-deploy-display-revisions for tagging our application builds and listing them, ember-cli-deploy-s3 to upload our application-build to Amazon-S3 and finally ember-cli-deploy-fastboot-app-server to zip the application build like fastboot-app-server expects us to do and ember-cli-deploy-app-server-aws to interact with the manifest-file that tells fastboot-app-server which version of our application should currently be served to users.

Here's a very basic config/deploy.js-configuration to tell ember-cli-deploy to do the right things. We simply need to give the s3- and fastboot-app-server-aws-plugins access to our storage-bucket and that's it:

module.exports = function(/* deployTarget */) {
  let ENV = {
    s3: {
      accessKeyId: process.env.S3_KEY,
      secretAccessKey: process.env.S3_SECRET,
      bucket: process.env.S3_BUCKET,
      region: process.env.S3_REGION,
    },
    'fastboot-app-server-aws': {
      accessKeyId: process.env.S3_KEY,
      secretAccessKey: process.env.S3_SECRET,
      bucket: process.env.S3_BUCKET,
      region: process.env.S3_REGION,
    }
  };
  
  return ENV;
};

Preview functionality

Unfortunately right now there's no notion of previewing uploaded builds in production with FastBoot like you may be used to when using the lightning-strategy when deploying your Ember.js-applications with ember-cli-deploy. fastboot-app-server is only able to serve one version of your application at a time as far as I am aware. So you would need to handle previews differently than usual. I haven't looked into detail yet on how this could be made possible and supported by the existing FastBoot-deploy-plugins but it would most likely involve deciding at the load-balancer layer to route requests to different servers or serverless-functions when users indicate that they want to be served preview-versions of your application. Of course you can and most likely should fallback to using a staging-environment[1] for your FastBoot-applications for now.

Conclusion

Due to the "new" FastBoot-deploy-plugins it is now very easy to deploy FastBoot-applications with ember-cli-deploy. Currently there is only one plugin available that expects you to work with Amazon-Web-Services to host your application-files and your manifest-file. Adding additional cloud-providers like Google Cloud for example would be very straight forward to do though. You would only need to create a deploy-plugin that will upload the manifest-file that fastboot-app-server uses to Google Cloud Storage and make the plugin update the manifest-file when running the ember deploy:activate-command.

Thanks to the rest of the ember-cli-deploy-core-team for making this all so easy and for being as awesome as they are. Kudos to you guys! ❤️🍻

Thanks for reading and as always just get in touch if you have questions. I'm available for consulting work and would be happy to help you and your company with your Ember.js-projects. You can have a look at the services that I provide here.


  1. I wrote a blog post on how to do staging-environments the right way a while back. Feel free to check it out here. ↩︎

Effective-Ember
© Effective Ember. Ember.js Consulting & Training by Michael Klein. All rights reserved. Impressum
This website uses cookies.