Deploying Ember.js applications

In this chapter we’ll explore different alternatives to deploy our Ember.js applications. We’ll talk about S3 and Pagefront based deployments where our application is completely separated from our API.

Deploying to S3

In order to host our application in S3, we’ll need to change our application adapter so it hits our CORS enabled API and then generate a production build.

To consume the API without using ember-cli’s proxy feature, we need to set the property host in the application adapter.

To do so, let’s add a configuration property called host in config/environment.js and then read it from there.

Adding host to config/environment.js
/* jshint node: true */

module.exports = function(environment) {
  var ENV = {
    host: 'https://api.ember-101.com',
    // ...

Now we can use it in the adapter. Let’s create the application adapter running ember g adapter application and then add the following:

app/adapters/application.js
import JSONAPIAdapter from 'ember-data/adapters/json-api';
import config from '../config/environment';

export default JSONAPIAdapter.extend({
  host: config.host
});

We also need to change app/routes/index.js to use the host:

app/routes/index.js
import Ember from 'ember';
import config from '../config/environment';

export default Ember.Route.extend({
  //
  // Check the following for more information about services
  // https://guides.emberjs.com/v2.5.0/applications/services/
  //
  ajax: Ember.inject.service(),
  model()  {
    return this.get('ajax').request(`${config.host}/friends`).then(function(data\
){
      return {
        friendsCount: data.data.length
      };
    });
  }
});

Now we can stop the server and run it again without the option --proxy.

Next we need to generate the production build using the command ember build.

When we run ember server, we always run a build and add some extra stuff so that we can run our project in development, but we don’t need the same files in production.

When we do ember build, the output goes by default to the directory dist. Let’s check that:

ember build
borrowers $ ember build
ember build
Building
Built project successfully. Stored in "dist/".

Inspecting the dist directory, we’ll see the following contents:

dist/
|-- assets
|-- |-- app.scss
|-- |-- borrowers.css
|-- |-- borrowers.js
|-- |-- borrowers.map
|-- |-- ember-basic-dropdown.scss
|-- |-- ember-power-select
|-- |-- |-- themes
|-- |-- |-- |-- bootstrap.scss
|-- |-- |-- variables.scss
|-- |-- ember-power-select.scss
|-- |-- failed.png
|-- |-- font
|-- |-- |-- fontello.eot
|-- |-- |-- fontello.svg
|-- |-- |-- fontello.ttf
|-- |-- |-- fontello.woff
|-- |-- |-- fontello.woff2
|-- |-- passed.png
|-- |-- test-loader.js
|-- |-- test-support.css
|-- |-- test-support.js
|-- |-- test-support.map
|-- |-- tests.js
|-- |-- tests.map
|-- |-- vendor.css
|-- |-- vendor.js
|-- |-- vendor.map
|-- crossdomain.xml
|-- index.html
|-- robots.txt
|-- testem.js
|-- tests
    |-- index.html

Let’s talk about the assets directory first. All our JavaScript and stylesheet files will end in this directory. We can also put other kinds of assets, such as images or fonts, under public/assets and they will be merged into this directory. If we had the image public/assets/images/foo.png we could reference it in our stylesheets like images/foo.png.

What about those test files? They are used for testing and only included in development or test environments. If we go to http://localhost:4200/tests and inspect the network tab, we’ll see that those files are being used.

The tests directory is the entry point for running tests. testem.js is used by default when we do ember test. It uses Testem to run the test with PhantomJS.

If we run the build command but we specify production environment (e.g., ember build --environment production) we’ll see a very different output:

dist/
|-- assets
|-- |-- app.scss
|-- |-- borrowers-0434066470763b4f6d79622e2bb60ffb.css
|-- |-- borrowers-b01655dbaa5eaca990dcb5f786c3a2b9.js
|-- |-- ember-basic-dropdown.scss
|-- |-- ember-power-select
|-- |-- |-- themes
|-- |-- |-- +-- bootstrap.scss
|-- |-- +-- variables.scss
|-- |-- ember-power-select.scss
|-- |-- font
|-- |-- |-- fontello.eot
|-- |-- |-- fontello.svg
|-- |-- |-- fontello.ttf
|-- |-- |-- fontello.woff
|-- |-- +-- fontello.woff2
|-- |-- vendor-6d05d317665a43d23c85eafd86e90654.css
|-- +-─ vendor-8422fb84936d9c467a1a18d2ad95d6c5.js
|-- crossdomain.xml
|-- index.html
+-─ robots.txt

We have fewer files this time. Nothing related with testing is included because that is only a development/tests concern. Our assets files were fingerprinted and minified. If we open dist/index.html we’ll see that the references to them were updated as well:

<link rel="stylesheet" href="assets/vendor-6d05d317665a43d23c85eafd86e90654.css">
<link rel="stylesheet" href="assets/borrowers-0434066470763b4f6d79622e2bb60ffb.c\
ss">

Fingerprinting is achieved using broccoli-asset-rev. This allows us the option to select the format of the files we want to fingerprint and to append an URL to every asset.

Now we are ready to deploy to an S3 bucket. We need to create the bucket and enable static website hosting. Let’s set up an index document, index.html.

The following guide explains how to set up your S3 bucket: Hosting a Static Website on Amazon S3

Once the bucket is set up, we can run ember build --environment production and then manually upload all the files under dist. The following is an example of the site working on S3: http://ember-101.s3-website-us-east-1.amazonaws.com/

It is very important that we set our bucket as public. To do this, we can use the following bucket policy:

S3 policy
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "AddPerm",
			"Effect": "Allow",
			"Principal": "*",
			"Action": "s3:GetObject",
			"Resource": "arn:aws:s3:::REPLACE-WITH-REAL-BUCKET-NAME/*"
		}
	]
}

The following tutorial explains how to achieve a setup using custom routing and Cloudfront: Hosting a Static Website on Amazon Web Services

If we decide to use Cloudfront, we need to prepend the URL to our assets. To do this, we simply pass the option in the Brocfile as follows:

Brocfile.js
var app = new EmberApp({
  fingerprint: {
    prepend: 'https://d29sqib8gy.cloudfront.net/'
  },
});

If we run ember build --environment production and open dist/index.html, we’ll notice the URL in our assets.

<script src="https://d29sqib8gy.cloudfront.net/assets/vendor-b29ae2f2e402c33a5d9\
c683aac4e0f8e.js"></script>
<script src="https://d29sqib8gy.cloudfront.net/assets/borrowers-c459411ce1cc8332\
ef795be81d96d1b6.js"></script>

A better approach for deployments would be to use the ember addon ember-cli-deploy. Their website has a complete guide on how to use their addon.

Deploying to Pagefront

Pagefront is a PaaS for ember. This is probably the easiest way to deploy ember applications today. They have an ember addon which makes the whole process super simple.

First let’s install the addon with ember install, we’ll use ember-101-GITHUB-HANDLE to identiy the application:

ember install ember-pagefront --app=ember-101-abuiles

After installing ember-pagefront, a new file config/deploy.js will be created with the required data to deploy to pagefront.

Next we can run ember deploy production and that’s it. Our application will be deployed to https://ember-101-abuiles.pagefrontapp.com

ember-cli-deploy

Ember CLI deploy has become the default solution to manage deployments with ember. Pagefront use it under the hood, and there are many other plugins available, which allow us to deploy to different platforms or just develop our own solutions.

We can find all the available options visiting the plugins section in their website http://ember-cli-deploy.com/docs/v0.6.x/plugins.