Deployment
When deploying your Ember.js applications with ember-cli-deploy, working with staging environments can be unintuitive. To do this cleanly you should not think of staging as an environment but in terms of a deploy-target you deploy your application to with a customized configuration. This post shows you how to do this properly.
Setting up staging deploys with
ember-cli-deploy
can be unintuitive because the default configuration of ember-cli
configures
your application based on environments
. This post will show you the right way to setup staging
deploys with ember-cli-deploy and explain the benefits of customizing your deploy workflow
around the idea of deploy-targets
instead of environments
.
This blog post is based on a post that I wrote on my old blog over four years ago. The patterns discussed still apply as well as they did back then and I want to make sure the best practice around Ember.js staging deployments stay well documented even when I take my old blog offline.
ember-cli-deploy
is the recommended and community agreed-upon way to deploy your
Ember.js applications. It comes with a lot of plugins that enable you to customize
your deployments and is one of the top-rated ember-cli
-addons on emberobserver
.
Here’s a great video of @lukemelia
and @grandazz
explaining the idea behind ember-cli-deploy
's deployment pipeline in great detail.
To put a long story short, you should be using ember-cli-deploy
to deploy your
ember-cli
-applications to production
.
Deploying to production
for most teams is only half the story of their
deployment workflow though. Most teams also deploy to a staging-environment,
an environment that mirrors production
as close as possible and is used to test
new features internally before releasing new code to the public.
Kind of unfortunately ember-cli
only supports three environments
development
,
testing
and production
and does not know anything about staging
-environments
when running the ember build-command. In a way, this makes sense
because staging is not a name for a pre-production-environment that all
teams in the world agree on. Some teams name the pre-production-environment
pre-production
or qa
, others simply need to support multiple
staging-environments at once.
Despite no notion of staging
, pre-production
and similar as environments in
ember-cli
, you can still deploy these kinds of “environments” with ember-cli-deploy
.
staging
and production
Because staging
is usually the last stage before a feature goes live into production
,
we want staging
to mirror production
as close as possible. This way we
hope, before going live, to identify issues that would otherwise only show up after
we released code to production
.
staging
will commonly be accessible via a different URL and will most likely use different
hosts for your API-services and use different API-Keys for 3rd party services that you use
in your application (error-tracking-, mapping-services, etc.), but other than
that it should behave exactly the same as production
.
This is important because this tells us that if we want to mirror what’s happening
in production
as close as possible, we don’t want to change the way our
application is built but only change certain configuration settings of the application we
deploy to staging
. This is not what environments do in ember-cli
though.
Environments are used by ember-cli
to customize the application build in general.
For example, when building for the production
-environment ember-cli
will minify
your application code via ember-cli-terser
, something that it won’t do for development
and test
by default.
After clarifying this, we now know what we want ember-cli-deploy
to do when
deploying to staging
. We want it to create a production
-like build but be able
to change certain configuration parameters based on config/environment.js
, and
we also want to be able to deploy to a different location than we do when
deploying to production
.
So how do we get ember-cli-deploy
to do the right thing for us? We need to do the following:
ember-cli-deploy
to deploy to a different location than when deploying to production
production
-buildconfig/environment.js
based on where we deploy toWhen taking a closer look at the /config/deploy.js
-configuration file that
ember-cli-deploy
creates for us when installing the addon, you see that ember-cli-deploy
does not concern itself with environment
s, it names these different stages of deployments
deployTargets
instead.
As you might have figured out already, this is by design and not an accidental misnomer.
environment
refers to how the application should be built, deployTarget
refers to what stage you want to deploy to. The deployTarget
that you see referenced in ember-cli-deploy
's
deploy-configuration will be set based on the target for your deployment you pass
to the ember deploy
-command. Examples:
# deployTarget 'production'
ember deploy production
# deployTarget 'staging'
ember deploy staging
# deployTarget 'pre-production'
ember deploy pre-production
ember-cli-deploy
uses the deployTarget
to customize the deployment. For
example, you can use the deployTarget
to change to which bucket the
index.html
-file ember-cli-deploy-build
built for you will be uploaded to by
ember-cli-deploy-s3-index
based on where you are deploying to:
Before uploading your application assets somewhere, you first have to build your
Ember.js application. When using ember-cli-deploy
you will use the
ember-cli-deploy-build
-plugin
to do that. The plugin does more of course, but to simplify a bit it will run
the ember build
-command that ember-cli
provides for you at the right time in the deployment
pipeline, passing whatever environment
you have configured in config/deploy.js
.
The most straight forward way to configure a staging
-build is thus something
like this:
Of course, as discussed in a previous section, this isn’t wrong technically but
will lead to problems because you are telling ember-cli-deploy-build
to build your application in the staging
-environment. ember-cli
does not know
about other environments than development
, test
and production
and nor do
other addons that you include in your application. Addons that you are including
can’t know about how your pre-production environments are called and won’t add
their dependencies in a production
-friendly way unless you build your application
in the production
-environment.
For example, ember-faker
will add all its fake
data to your staging
-build which will bloat your application and won’t mirror your
production
-build as you’d want staging
to do.
What we need to do for the build instead, is to use the production
-environment
to build the application:
But you still need to pass staging
to the build command as this is used to
build your application’s config/environment.js
-file that will be included in
the bootstrap index.html
that you will serve to your users. Right?! No.
environment.js
As it turns out it’s pretty easy to build a correct production
-like
staging
-build because building your application is based on three files:
config/deploy.js
, config/environment.js
and ember-cli-build.js
.
config/deploy.js
- used to customize the deploymentconfig/environment.js
- used to customize configuration settings like API-URLs based on an environment
ember-cli-build.js
- contains the build specification for Broccoli. Used for customizing the build of your application (customize fingerprinting, manually including JS-dependencies etc.)ember-cli
will create the environment-configuration it includes in your app’s
index.html
based on the function exported in config/environment.js
that gets
passed the environment from the ember build
-command.
As it turns out, creating a production
-like-build with a different configuration from config/environment.js
in index.html
is pretty easy. You just have to change the checks for
environment
, that gets passed into the function in config/environment.js
, from
the passed-in environment
to the DEPLOY_TARGET
environment-variable that
ember-cli-deploy
will set for you when executing a deploy:
You can use the same idea when you need to customize settings based on the
deploy
-target in ember-cli-build.js
- the DEPLOY_TARGET
-environment-variable
will be available there as well.
That’s all there is to it. A long post for an easy concept. When you need
to configure your application based on where you are deploying to, use the
DEPLOY_TARGET
-environment-variable that ember-cli-deploy
will setup for you
when executing a deploy. Don’t change the build environment
because for
staging
-deployments you want to mirror the production
build and only change
certain configurations of your application.
With this setup, you can deploy to multiple
production
-like deployTargets
and customize their configurations and deployments
quite easily.
Thanks to the ember-cli-deploy -team 👋 for a great deployment pipeline and @pangratz for valuable discussions on this topic 🍻.
ember-cli-deploy
makes it easy to setup a deployment for your Ember.js
application but sometimes teams have very complex requirements for their
deployment pipelines. Don’t hesitate to
if your team does. We are here to help your teams deliver
ambitious applications to production
- and staging
🙃 - with confidence.
If you have questions or want to share your thoughts about this post with me
you can find me on
Twitter
- I’m always interested in hearing about your experiences with
ember-cli-deploy
and challenges you face when deploying your Ember.js apps.
We are here to enable your team to deliver ambitious applications. Let's discuss how we can help.