Getting Started

Prerequisites

Node

First, install the latest version of Node.

To do so, either follow the installation instructions on nodejs.org, or use your preferred package manager (such as Homebrew on OSX) if you have one.

After the installation is complete, verify that Node is set up correctly by typing the below commands on the command line. Both should output a version number:

node -v
npm -v

Ember CLI

Once you’ve installed Node, you’ll need to globally install Ember CLI:

npm install -g ember-cli

This will give you access to the ember command-line runner.

Bower

You’ll need to globally install Bower, a package manager that keeps your front-end dependencies (including jQuery, Ember, and QUnit) up-to-date:

npm install -g bower

This will give you access to the bower command-line runner.

Watchman

On OSX and UNIX-like operating systems, we recommend installing Watchman version 3.x, which provides Ember CLI a more effective way for watching project changes.

File-watching on OSX is error-prone and Node’s built-in NodeWatcher has trouble observing large trees. Watchman on the other hand, solves these problems and performs well on extremely massive file trees. You can read more about Facebook’s motivations here.

On OSX, you can install Watchman using Homebrew:

brew install watchman

For complete installation instructions, refer to the docs on the Watchman website. Note, there exists a similarly named npm package (watchman) which is not the intended installation. If you have this package installed you may see the following warning:

invalid watchman found, version: [2.9.8] did not satisfy [^3.0.0], falling back to NodeWatcher

If you intend on using the npm version for another purpose, make sure it’s not on your PATH otherwise, remove it using:

npm uninstall -g watchman

When in doubt, use the following command to inspect which Watchman(s) you have:

which -a watchman

Lastly, when Watchman is not installed, a notice is displayed when invoking various commands. You can safely ignore this message:

Could not find watchman, falling back to NodeWatcher for file system events

PhantomJS

With Ember CLI, you can use the automated test runner of your choice, however most testing services will recommend or require PhantomJS, which you can install via npm or the PhantomJS website. Note, PhantomJS is the default test runner for Testem and Karma.

If you want to use PhantomJS to run your integration tests, it must be globally installed:

npm install -g phantomjs-prebuilt

Create a new project

Run the new command along with the desired app name to create a new project:

ember new my-new-app

Ember CLI will create a new my-new-app directory and in it, generate the application structure.

Once the generation process is complete, launch the app:

cd my-new-app
ember server

Navigate to http://localhost:4200 to see your new app in action.

Navigate to http://localhost:4200/tests to see your test results in action.

Migrating an existing Ember project that doesn’t use Ember CLI

If your app uses the deprecated Ember App Kit, there is a migration guide located on the README.

If your app uses globals (e.g. App.Post) from a different build pipeline such as Grunt, Ember-Rails, or Gulp, you can try using the Ember CLI migrator. The Ember CLI migrator is a command line tool that looks at your JavaScript code using a JavaScript parser and rewrites it to ES6 following Ember CLI’s conventions. The migrator keeps your code style and keeps git history available via git log --follow.

Cloning an existing project

If you are checking out an existing Ember CLI-based project, you will need to install npm and bower dependencies before running the server:

git clone git@github.com:me/my-app.git
cd my-app
npm install
bower install
ember server

Using Ember CLI

Command Purpose
ember Prints out a list of available commands.
ember new <app-name> Creates a directory called <app-name> and in it, generates an application structure. If git is available the directory will be initialized as a git repository and an initial commit will be created. Use --skip-git flag to disable this feature.
ember init Generates an application structure in the current directory.
ember build Builds the application into the dist/ directory (customize via the --output-path flag). Use the --environment flag to specify the build environment (defaults to development). Use the --watch flag to keep the process running and rebuilding when changes occur.
ember server Starts the server. The default port is 4200. Use the --proxy flag to proxy all ajax requests to the given address. For example, ember server --proxy http://127.0.0.1:8080 will proxy all ajax requests to the server running at http://127.0.0.1:8080. Aliases: ember s, ember serve
ember generate <generator-name> <options> Runs a specific generator. To see available generators, run ember help generate. Alias: ember g
ember destroy <generator-name> <options> Removes code created by the generate command. If the code was generated with the --pod flag, you must use the same flag when running the destroy command. Alias: ember d
ember test Run tests with Testem in CI mode. You can pass any options to Testem through a testem.json file. By default, Ember CLI will search for it under your project’s root. Alternatively, you can specify a config-file. Alias: ember t
ember install <addon-name> Installs the given addon into your project and saves it to the package.json file. If provided, the command will run the addon’s default blueprint.

Folder Layout

File/directory Purpose
app/ Contains your Ember application’s code. Javascript files in this directory are compiled through the ES6 module transpiler and concatenated into a file called <app-name>.js. See the table below for more details.
dist/ Contains the distributable (optimized and self-contained) output of your application. Deploy this to your server!
public/ This directory will be copied verbatim into the root of your built application. Use this for assets that don’t have a build step, such as images or fonts.
tests/ Includes your app’s unit and integration tests, as well as various helpers to load and run the tests.
tmp/ Temporary application build-step and debug output.
bower_components/ Bower dependencies (both default and user-installed).
node_modules/ npm dependencies (both default and user-installed).
vendor/ Your external dependencies not installed with Bower or npm.
.jshintrc JSHint configuration.
.gitignore Git configuration for ignored files.
ember-cli-build.js Contains the build specification for Broccoli.
bower.json Bower configuration and dependency list. See Managing Dependencies.
package.json npm configuration and dependency list. Mainly used to list the dependencies needed for asset compilation.

Layout within app directory

File/directory Purpose
app/app.js Your application’s entry point. This is the first executed module.
app/index.html The only page of your single-page app! Includes dependencies, and kickstarts your Ember application. See app/index.html.
app/router.js Your route configuration. The routes defined here correspond to routes in app/routes/.
app/styles/ Contains your stylesheets, whether SASS, LESS, Stylus, Compass, or plain CSS (though only one type is allowed, see Asset Compilation). These are all compiled into <app-name>.css.
app/templates/ Your HTMLBars templates. These are compiled to /dist/assets/<app-name>.js. The templates are named the same as their filename, minus the extension (i.e. templates/foo/bar.hbs -> foo/bar).
app/controllers/, app/models/, etc. Modules resolved by the Ember CLI resolver. See Using Modules & the Resolver.

app/index.html

The app/index.html file lays the foundation for your application. This is where the basic DOM structure is laid out, the title attribute is set, and stylesheet/javascript includes are done. In addition to this, app/index.html includes multiple hooks - {{content-for 'head'}} and {{content-for 'body'}} - that can be used by addons to inject content into your application’s head or body. These hooks need to be left in place for your application to function properly however, they can be safely ignored unless you are directly working with a particular addon.

Addons

Addons are registered in npm with a keyword of ember-addon. See a full list of existing addons registered in NPM here.

Developing on a subpath

If your app isn’t running on the root URL (/), but on a subpath (like /my-app/), your app will only be accessible on /my-app/ and not on /my-app, too. Sometimes, this can be a bit annoying. Therefore you should take the following snippet as an example for a simple route which takes you to the right URL if you’ve entered the wrong one:

// index.js
app.get('/my-app', function(req, res, next) {

  if (req.path != '/my-app/') {
    res.redirect('/my-app/');
  } else {
    next();
  }

});

Just place it within the index.js file of your app’s /server directory (so that it gets applied when the ember-cli development server is being started). The snippet simply tests if the URL that is beeing accessed begins with /my-app/. And if it doesn’t, you’ll get redirected. Otherwise, the redirection will be skipped.

Using Modules & the Resolver

The Ember Resolver is the mechanism responsible for looking up code in your application and converting its naming conventions into the actual classes, functions, and templates that Ember needs to resolve its dependencies, for example, what template to render for a given route. For an introduction to the Ember Resolver, and a basic example of how it actually works, see this video by Robert Jackson.

In the past, Ember’s Default Resolver worked by putting everything into a global namespace, so you will come across the following pattern:

App.IndexRoute = Ember.Route.extend({
  model: function() {
    return ['red', 'yellow', 'blue'];
  }
});

Today, Ember CLI uses a newer version of the Resolver based on ES6 semantics. This means that you can build your apps using syntax from future JavaScript versions, but output AMD modules that can be used by existing JavaScript libraries today.

For example, this route definition in app/routes/index.js would result in a module called your-app/routes/index. Using the resolver, when Ember looks up the index route, it will find this module and use the object that it exports.

// app/routes/index.js
import Ember from "ember";

export default Ember.Route.extend({
  model: function() {
    return ['red', 'yellow', 'blue'];
  }
});

You can also require modules directly with the following syntax:

import FooMixin from "./mixins/foo";

You can reference a module by using either a relative or absolute path. If you would like to reference a module using absolute begin the path with the app name defined in package.json:

import FooMixin from "appname/mixins/foo";

Similarly, you can give any name to the variable into which you import a module when doing so manually; see how the module mixins/foo is assigned to variable FooMixin in the example above.

Using Ember or Ember Data

To use Ember or DS (for Ember Data) in your modules you must import them:

import Ember from "ember";
import DS from "ember-data";

Using Pods

One of the enhancements that the new Resolver brings is that it will first look for Pods before the traditional project structure.

Module Directory Naming Structure

Directory Purpose
app/adapters/ Adapters with the convention adapter-name.js.
app/components/ Components with the convention component-name.js. Components must have a dash in their name. So blog-post is an acceptable name, but post is not.
app/helpers/ Helpers with the convention helper-name.js. Helpers must have a dash in their name. Remember that you must register your helpers by exporting makeBoundHelper or calling registerBoundHelper explicitly.
app/initializers/ Initializers with the convention initializer-name.js. Initializers are loaded automatically.
app/mixins/ Mixins with the convention mixin-name.js.
app/models/ Models with the convention model-name.js.
app/routes/ Routes with the convention route-name.js. Child routes are defined in sub-directories, parent/child.js. To provide a custom implementation for generated routes (equivalent to App.Route when using globals), use app/routes/basic.js.
app/serializers/ Serializers for your models or adapter, where model-name.js or adapter-name.js.
app/transforms/ Transforms for custom Ember Data attributes, where attribute-name.js is the new attribute.
app/utils/ Utility modules with the convention utility-name.js.

All modules in the app directory can be loaded by the resolver but typically classes such as mixins and utils should be loaded manually with an import statement.

For more information, see Naming Conventions.

Resolving Handlebars helpers

Custom Handlebars helpers are one of the ways that you can use the same HTML multiple times in your web application. Registering your custom helper allows it to be invoked from any of your Handlebars templates. Custom helpers are located under app/helpers.

// app/helpers/upper-case.js
import Ember from "ember";

export default Ember.Helper.helper(function([value]) {
  return value.toUpperCase();
});

In some-template.hbs:

{{upper-case "foo"}}

While previous versions of ember-cli required auto-resolved helpers only if they contain a dash, now all helpers are auto-resolved, regardless of whether they contain a dash or not.

A common pattern with helpers is to define a helper to use your views (e.g. for a custom text field view, MyTextField a helper my-text-field to use it). It is advised to leverage Components instead.

Do this:

// Given... app/components/my-text-field.js
import Ember from "ember";

export default Ember.TextField.extend({
  // some custom behaviour...
});

Using global variables or external scripts

If you want to use external libraries that write to a global namespace (e.g. moment.js), you need to add those to the predef section of your project’s .jshintrc file and set its value to true. If you use the lib in tests, you need to add it to your tests/.jshintrc file, too.

Naming Conventions

Overview

  • kebab-case
    • file names
    • directory names
    • html tags/ember components
    • CSS classes
    • URLs
  • camelCase
    • JavaScript
    • JSON

When using Ember CLI it’s important to keep in mind that the Resolver changes some of the naming conventions you would typically use out of the box with Ember, Ember Data and Handlebars. In this section we review some of these naming conventions.

Module Examples

Adapters
// app/adapters/application.js
import Ember from "ember";
import DS from "ember-data";

export default DS.RESTAdapter.extend({});
Components
// app/components/time-input.js
import Ember from "ember";

export default Ember.TextField.extend({});
Controllers
// app/controllers/stop-watch.js
import Ember from "ember";

export default Ember.Controller.extend({});

And if it’s a nested controller, we can declare nested/child controllers like such: app/controllers/posts/index.js.

Helpers
// app/helpers/format-time.js
import Ember from "ember";

export default Ember.Helper.helper(function(){});
Initializers
// app/initializers/observation.js
export default {
  name: 'observation',
  initialize: function() {
    // code
  }
};

Note: initializers are loaded automatically.

Mixins
// app/mixins/evented.js
import Ember from "ember";

export default Ember.Mixin.create({});
Models
// app/models/observation.js
import DS from "ember-data";

export default DS.Model.extend({});
Routes
// app/routes/timer.js
import Ember from "ember";

export default Ember.Route.extend({});

Nested routes as such: app/routes/timer/index.js or app/routes/timer/record.js.

Serializers
// app/serializers/observation.js
import DS from "ember-data";

export default DS.RESTSerializer.extend({});
Transforms
// app/transforms/time.js
import DS from "ember-data";

export default DS.Transform.extend({});
Utilities
// app/utils/my-ajax.js
export default function myAjax() {};
Views
<!-- app/index.hbs -->
{{view 'stop-watch'}}
// app/views/stop-watch.js
import Ember from "ember";

export default Ember.View.extend({});

And views, which can be referenced in sub-directories, but have no inheritance.

<!-- app/index.hbs -->
{{view 'inputs/time-input'}}
// app/views/inputs/time-input.js
import Ember from "ember";

export default Ember.TextField.extend({});

Filenames

It is important to keep in mind that the Resolver uses filenames to create the associations correctly. This helps you by not having to namespace everything yourself. But there are a couple of things you should know.

All filenames should be lowercased
// models/user.js
import Ember from "ember";
export default Ember.Model.extend();
Dasherized file and directory names are required
// controllers/sign-up.js
import Ember from "ember";
export default Ember.Controller.extend();
Nested directories

If you prefer to nest your files to better manage your application, you can easily do so.

// controllers/posts/new.js results in a controller named "controllers.posts/new"
import Ember from "ember";
export default Ember.Controller.extend();

You cannot use paths containing slashes in your templates because Handlebars will translate them back to dots. Simply create an alias like this:

// controllers/posts.js
import Ember from "ember";
export default Ember.Controller.extend({
  needs: ['posts/details'],
  postsDetails: Ember.computed.alias('controllers.posts/details')
});
<!-- templates/posts.hbs -->
<!-- because {{controllers.posts/details.count}} does not work -->
{{postsDetails.count}}

Tests

Test filenames should be suffixed with -test.js in order to run.

Pod structure

As your app gets bigger, a feature-driven structure may be better. Splitting your application by functionality/resource would give you more power and control to scale and maintain it. As a default, if the file is not found on the POD structure, the Resolver will look it up within the normal structure.

In this case, you should name the file as its functionality. Given a resource Users, the directory structure would be:

  • app/users/controller.js
  • app/users/route.js
  • app/users/template.hbs

Rather than hold your resource directories on the root of your app you can define a POD path using the attribute podModulePrefix within your environment configs. The POD path should use the following format: {appname}/{poddir}.

// config/environment.js
module.exports = function(environment) {
  var ENV = {
    modulePrefix: 'my-new-app',
    // namespaced directory where resolver will look for your resource files
    podModulePrefix: 'my-new-app/pods',
    environment: environment,
    baseURL: '/',
    locationType: 'auto'
    //...
  };

  return ENV;
};

Then your directory structure would be:

  • app/pods/users/controller.js
  • app/pods/users/route.js
  • app/pods/users/template.hbs

Using With Ember Data

The current version of Ember Data is included with Ember CLI.

Ember Data has undergone some major reboots, drastically simplifying it and making it easier to use with the Ember resolver. Here’s some tips for using it within Ember CLI.

To use ember-cli without Ember Data remove the dependency from package.json (the same applies for ic-ajax)

npm rm ember-data --save-dev

Models

Models are critical in any dynamic web application. Ember Data makes making models extremely easy.

For example, we can create a todo model like so:

// models/todo.js
import DS from "ember-data";

export default DS.Model.extend({
  title: DS.attr('string'),
  isCompleted: DS.attr('boolean'),
  quickNotes: DS.hasMany('quick-note')
});

// models/quick-note.js
import DS from "ember-data";

export default DS.Model.extend({
  name: DS.attr('string'),
  todo: DS.belongsTo('todo')
});

Note, that filenames should be all lowercase and dasherized - this is used by the Resolver automatically.

Adapters & Serializers

Ember Data makes heavy use of per-type adapters and serializers. These objects can be resolved like any other.

Adapters can be placed at /app/adapters/type.js:

// adapters/post.js
import DS from "ember-data";

export default DS.RESTAdapter.extend({});

And it’s serializer can be placed in /app/serializers/type.js:

// serializers/post.js
import DS from "ember-data";

export default DS.RESTSerializer.extend({});

Application-level (default) adapters and serializers should be named adapters/application.js and serializers/application.js, respectively.

Mocks and fixtures

If you’re used to using fixtures to get test data into your app during development, you won’t be able to create fixture data like you’re used to doing (i.e. as specified in the guides). This is because the models in your Ember CLI app (like all other objects) aren’t attached to the global namespace.

Ember CLI comes with an http-mock generator which is preferred to fixtures for development and testing. Mocks have several advantages over fixtures, a primary one being that they interact with your application’s adapters. Since you’ll eventually be hooking your app up to a live API, it’s wise to be testing your adapters from the onset.

To create a mock for a posts API endpoint, use

ember g http-mock posts

A basic ExpressJS server will be scaffolded for your endpoint under /your-app/server/mocks/posts.js. Once you add the appropriate JSON response, you’re ready to go. The next time you run ember server, your new mock server will be listening for any API requests from your Ember app.

Note: Mocks are just for development. The entire /server directory will be ignored during ember build and ember test.

If you decide to use fixtures instead of mocks, you’ll need to use reopenClass within your model class definitions. First, create a fixture adapter, either for a single model or your entire application:

// adapters/application.js
import DS from "ember-data";

export default DS.FixtureAdapter.extend({});

Then add fixture data to your model class:

// models/author.js
import DS from "ember-data";

var Author = DS.Model.extend({
  firstName: DS.attr('string'),
  lastName: DS.attr('string')
});

Author.reopenClass({
  FIXTURES: [
    {id: 1, firstName: 'Bugs', lastName: 'Bunny'},
    {id: 2, firstName: 'Wile E.', lastName: 'Coyote'}
  ]
});

export default Author;

Your Ember app’s API requests will now use your fixture data.

Testing

Running existing tests

Running your tests is as easy as one of these commands:

ember test            # will run your test-suite in your current shell once
ember test --server   # will run your tests on every file-change
ember t -s -m 'Unit | Utility | name' # will run only the unit test module for a utility by `name`, on every change
ember t -f 'match a phrase in test description(s)' # will run only the tests with a description that matches a phrase

Alternatively you can run the tests in your regular browser using the QUnit interface. Run ember server and navigate to http://localhost:4200/tests. When the app runs in /tests it runs in the development environment, not the test environment.

Writing a test

  • ember-testing
  • helpers
  • unit/acceptance

The default tests in Ember CLI use the QUnit library, though Mocha / Chai testing is possible using ember-cli-mocha. The included tests demonstrate how to write both unit tests and acceptance/integration tests using the new ember-testing package.

Test filenames should be suffixed with -test.js in order to run.

If you have manually set the locationType in your environment.js to hash or none you need to update your tests/index.html to have absolute paths (/assets/vendor.css and /testem.js vs the default relative paths).

CI Mode with Testem

ember test will run your tests with Testem on CI mode. You can pass any option to Testem using a configuration file.

If you are capturing output from the Testem xunit reporter, use ember test --silent to silence unwanted output such as the ember-cli version. If you want to capture output to a file you can use report_file: "path/to/file.xml" in your testem.json config file.

By default, your integration tests will run on PhantomJS. You can install via npm:

npm install -g phantomjs-prebuilt

We plan to make your test runner pluggable, so you can use your favorite runner.

Using ember-qunit for integration tests

All Ember Apps come with built-in ember test helpers, which are useful for writing integration tests. In order to use them, you will need to import tests/helpers/start-app.js, which injects the required helpers.

Be sure to use the module function to invoke beforeEach and afterEach.

import Ember from "ember";
import { module, test } from 'qunit';
import startApp from '../helpers/start-app';
var App;

module('An Integration test', {
  beforeEach: function() {
    App = startApp();
  },
  afterEach: function() {
    Ember.run(App, App.destroy);
  }
});

test("Page contents", function(assert) {
  assert.expect(2);
  visit('/foos').then(function() {
    assert.equal(find('.foos-list').length, 1, "Page contains list of models");
    assert.equal(find('.foos-list .foo-item').length, 5, "List contains expected number of models");
  });
});

Using ember-qunit for unit tests

An Ember CLI-generated project comes pre-loaded with ember-qunit which includes several helpers to make your unit-testing life easier, i.e.:

  • moduleFor
  • moduleForModel
  • moduleForComponent
moduleFor(fullName, description, callbacks, delegate)

The generic resolver that will load what you specify. The usage closely follows QUnit’s own module function. It’s use can be seen within the supplied index-test.js:

// tests/unit/routes/index-test.js
import { test, moduleFor } from 'ember-qunit';

moduleFor('route:index', "Unit - IndexRoute", {
  // only necessary if you want to load other items into the runtime
  // needs: ['controller:index']
  beforeEach: function () {},
  afterEach: function () {}
});

test("it exists", function(assert){
  assert.ok(this.subject());
});

fullname

The resolver friendly name of the object you are testing.

description

The description that will group all subsequent tests under. Defaults to the fullname.

callbacks

You are able to supply custom beforeEach, afterEach, & subject functionality by passing them into the callbacks parameter. If other objects should be loaded into Ember.js, specify the objects through the needs property.

delegate

To manually modify the container & the testing context, supply a function as the delegate matching this signature delegate(container, testing_context).

this.subject() calls the factory for the object specified by the fullname and will return an instance of the object.

moduleForModel(name, description, callbacks)

Extends the generic moduleFor with custom loading for testing models:

// tests/unit/models/post-test.js
import DS from 'ember-data';
import Ember from 'ember';
import { test, moduleForModel } from 'ember-qunit';

moduleForModel('post', 'Post Model', {
  needs: ['model:comment']
});

test('Post is a valid ember-data Model', function (assert) {
  var store = this.store();
  var post = this.subject({title: 'A title for a post', user: 'bob'});
  assert.ok(post);
  assert.ok(post instanceof DS.Model);

  // set a relationship
  Ember.run(function() {
    post.set('comment', store.createRecord('comment', {}))
  });

  assert.ok(post.get('comment'));
  assert.ok(post.get('comment') instanceof DS.Model);
});

name

The name of the model you are testing. It is necessary to only supply the name, not the resolver path to the object(model:post => post).

description

The description that will group all subsequent tests under. Defaults to the name.

callbacks

You are able to supply custom beforeEach, afterEach, & subject functionality by passing them into the callbacks parameter. If other objects should be loaded into Ember.js, specify the objects through the needs property.

Note: If the model you are testing has relationships to any other model, those must be specified through the needs property.

this.store() retrieves the DS.Store.

this.subject() calls the factory for the DS.Model specified by the fullname and will return an instance of the object.

moduleForComponent(name, description, callbacks)

Extends the generic moduleFor with custom loading for testing components:

// tests/integration/components/pretty-color-test.js
import Ember from "ember";
import { test, moduleForComponent } from 'ember-qunit';

moduleForComponent('pretty-color');

test('changing colors', function(assert){
  var component = this.subject();

  Ember.run(function(){
    component.set('name','red');
  });

  // first call to $() renders the component.
  assert.equal(this.$().attr('style'), 'color: red;');

  Ember.run(function(){
    component.set('name', 'green');
  });

  assert.equal(this.$().attr('style'), 'color: green;');
});

name

The name of the component you are testing. It is necessary to only supply the name, not the resolver path to the object(component:pretty-color => pretty-color).

description

The description that will group all subsequent tests under. Defaults to the name.

callbacks

You are able to supply custom beforeEach, afterEach, & subject functionality by passing them into the callbacks parameter. If other objects should be loaded into Ember.js, specify the objects through the needs property.

this.subject() calls the factory for the Ember.Component specified by the fullname and will return an instance of the object.

The first call this.$() will render out the component. So if you want to test styling, you must access the component via jQuery.

Writing your own test helpers

Ember testing provides that ability to register your own test helpers. In order to use these with ember-cli they must be registered before startApp is defined.

Depending on your approach, you may want to define one helper per file or a group of helpers in one file.

Single helper per file

// helpers/routes-to.js
import Ember from "ember";

export default Ember.Test.registerAsyncHelper('routesTo', function (app, assert, url, route_name) {
  visit(url);
  andThen(function () {
    assert.equal(currentRouteName(), route_name, 'Expected ' + route_name + ', got: ' + currentRouteName());
  });
});

This can then be used in start-app.js, like this

// helpers/start-app.js
import routesTo from './routes-to';

export default function startApp(attrs) {
//...

Group of helpers in one file

An alternative approach is to create a bunch of helpers wrapped in a self calling function, like this

// helpers/custom-helpers.js
var customHelpers = function() {
  Ember.Test.registerHelper('myGreatHelper', function (app) {
    //do awesome test stuff
  });

  Ember.Test.registerAsyncHelper('myGreatAsyncHelper', function (app) {
    //do awesome test stuff
  });
}();

export default customHelpers;

which can be used in start-app.js

// helpers/start-app.js
import customHelpers from './custom-helpers';

export default function startApp(attrs) {
//...

Once your helpers are defined, you’ll want to ensure that they are listing in the .jshintrc file within the test directory.

// /tests/.jshintrc
{
  "predef": [
    "document",
    //...
    "myGreatHelper",
    "myGreatAsyncHelper"

Asset Compilation

Raw Assets

  • public/assets vs app/styles

To add images, fonts, or other assets, place them in the public/assets directory. For example, if you place logo.png in public/assets/images, you can reference it in templates with assets/images/logo.png or in stylesheets with url('/assets/images/logo.png').

Minifying

The compiled css-files are minified by broccoli-clean-css or broccoli-csso, if it is installed locally. You can pass minifer-specific options to them using the minifyCSS:options object in your ember-cli-build. Minification is enabled by default in the production-env and can be disabled using the minifyCSS:enabled switch.

Similarly, the js-files are minified with broccoli-uglify-js in the production-env by default. You can pass custom options to the minifier via the minifyJS:options object in your ember-cli-build. To enable or disable JS minification you may supply a boolean value for minifyJS:enabled.

For example, to disable minifying of CSS and JS, add in ember-cli-build.js:

// ember-cli-build.js
var EmberApp = require('ember-cli/lib/broccoli/ember-app');

module.exports = function(defaults) {
  var app = new EmberApp(defaults, {
    minifyJS: {
      enabled: false
    },
    minifyCSS: {
      enabled: false
    }
  });

  //...
  return app.toTree();
};

Exclude from minification

To exclude assets from dist/assets from being minificated, one can pass options for broccoli-uglify-sourcemap like so:

// ember-cli-build.js
var EmberApp = require('ember-cli/lib/broccoli/ember-app');

module.exports = function(defaults) {
  var app = new EmberApp(defaults, {
    minifyJS: {
      options: {
        exclude: ["**/vendor.js"]
      }
    }
  });

  //...
  return app.toTree();
};

This would exclude the resulting vendor.js file from being minificated.

Source Maps

Ember CLI supports producing source maps for your concatenated and minified JS source files.

Source maps are configured by the EmberApp sourcemaps option, and are disabled in production by default. Pass sourcemaps: {enabled: true} to your EmberApp constructor to enable source maps for javascript. Use the extensions option to add other formats, such as coffeescript and CSS: {extensions: ['js', 'css', 'coffee']}. JS is supported out-of-the-box. CSS is not currently supported. For other source formats (Sass, Coffee, etc) refer to their addons.

Default ember-cli-build.js:

import EmberApp from 'ember-cli/lib/broccoli/ember-app';
var app = new EmberApp({
  sourcemaps: {
    enabled: EmberApp.env() !== 'production',
    extensions: ['js']
  }
});

Stylesheets

Ember CLI supports plain CSS out of the box. You can add your css styles to app/styles/app.css and it will be served at assets/application-name.css.

For example, to add bootstrap in your project you need to do the following:

bower install bootstrap --save

In ember-cli-build.js add the following:

app.import('bower_components/bootstrap/dist/css/bootstrap.css');

it’s going to tell Broccoli that we want this file to be concatenated with our vendor.css file.

To use a CSS preprocessor, you’ll need to install the appropriate Broccoli plugin. When using a preprocessor, Broccoli is configured to look for an app.less, app.scss, app.sass, or app.styl manifest file in app/styles. This manifest should import any additional stylesheets.

All your preprocessed stylesheets will be compiled into one file and served at assets/application-name.css.

If you would like to change this behavior, or compile to multiple output stylesheets, you can adjust the Output Paths Configuration

CSS

To use plain CSS with app.css:

  • Write your styles in app.css and/or organize your CSS into multiple stylesheet files and import these files with @import from within app.css.
  • CSS @import statements (e.g. @import 'typography.css';) must be valid CSS, meaning @import statements must precede all other rules and so be placed at the top of app.css.
  • In the production build, the @import statements are replaced with the contents of their files and the final minified, concatenated single CSS file is built to dist/assets/yourappname-FINGERPRINT_GOES_HERE.css.
  • Any individual CSS files are also built and minified into dist/assets/ in case you need them as standalone stylesheets.
  • Relative pathing gets changed (how to customize?)

Example app.css with valid @import usage:

/* @imports must appear at top of stylesheet to be valid CSS */
@import 'typography.css';
@import 'forms.css';

/* Any CSS rules must go *after* any @imports */
.first-css-rule {
  color: red;
}
...

CSS Preprocessors

To use one of the following preprocessors, all you need to do is install the appropriate NPM module. The respective files will be picked up and processed automatically.

LESS

To enable LESS, you’ll need to add ember-cli-less to your NPM modules.

ember install ember-cli-less

SCSS/SASS

To enable SCSS/SASS, you’ll need to install the ember-cli-sass addon to your project (defaults to .scss, .sass allowed via configuration).

ember install ember-cli-sass

You can configure your project to use .sass in your ember-cli-build.js:

// ember-cli-build.js
var app = new EmberApp(defaults, {
  sassOptions: {
    extension: 'sass'
  }
});

Compass

To use Compass with your ember-cli app, install ember-cli-compass-compiler addon using NPM.

ember install ember-cli-compass-compiler

Stylus

To enable Stylus, you must first add ember-cli-stylus to your NPM modules:

ember install ember-cli-stylus

CoffeeScript

To enable CoffeeScript, you must first add ember-cli-coffeescript to your NPM modules:

ember install ember-cli-coffeescript

The modified package.json should be checked into source control. CoffeeScript can be used in your app’s source and in tests, just use the .coffee extension on any file.

The ES6 module transpiler does not directly support CoffeeScript, but using them together is simple. Use the ` character to escape out to JavaScript from your .coffee files, and use the ES6 syntax there:

# app/models/post.coffee
`import Ember from 'ember'`
`import User from 'appkit/models/user'`

Post = Ember.Object.extend
  init: (userId) ->
    @set 'user', User.findById(userId)

`export default Post`

Note that earlier versions of the transpiler had explicit support for CoffeeScript, but that support has been removed.

EmberScript

To enable EmberScript, you must first add broccoli-ember-script to your NPM modules:

npm install broccoli-ember-script --save-dev

Note that the ES6 module transpiler is not directly supported with Emberscript, to allow use of ES6 modules use the ` character to escape raw Javascript similar to the CoffeeScript example above.

Emblem

For Emblem, run the following commands:

ember install ember-cli-emblem

If you’re using the older broccoli-emblem-compiler addon, you need to switch to ember-cli-emblem. The older broccoli-emblem-compiler compiles directly to JS instead of Handlebars and therefore is broken on all newer version of HTMLBars.

Fingerprinting and CDN URLs

Fingerprinting is done using the addon broccoli-asset-rev (which is included by default).

When the environment is production (e.g. ember build --environment=production), the addon will automatically fingerprint your js, css, png, jpg, and gif assets by appending an md5 checksum to the end of their filename (e.g. assets/yourapp-9c2cbd818d09a4a742406c6cb8219b3b.js). In addition, your html, js, and css files will be re-written to include the new name. There are a few options you can pass in to EmberApp in your ember-cli-build.js to customize this behavior.

  • enabled - Default: app.env === 'production' - Boolean. Enables fingerprinting if true. True by default if current environment is production.
  • exclude - Default: [] - An array of strings. If a filename contains any item in the exclude array, it will not be fingerprinted.
  • ignore - Default: [] - An array of strings. If a filename contains any item in the ignore array, the contents of the file will not be processed for fingerprinting.
  • extensions - Default: ['js', 'css', 'png', 'jpg', 'gif', 'map'] - The file types to add md5 checksums.
  • prepend - Default: '' - A string to prepend to all of the assets. Useful for CDN urls like https://subdomain.cloudfront.net/
  • replaceExtensions - Default: ['html', 'css', 'js'] - The file types to replace source code with new checksum file names.
  • customHash - When specified, this is appended to fingerprinted filenames instead of the md5. Pass null to suppress the hash, which can be useful when using prepend.

As an example, this ember-cli-build will exclude any file in the fonts/169929 directory as well as add a cloudfront domain to each fingerprinted asset.

// ember-cli-build.js
var app = new EmberApp({
  fingerprint: {
    exclude: ['fonts/169929'],
    prepend: 'https://subdomain.cloudfront.net/'
  }
});

The end result will turn

<script src="assets/appname.js">
background: url('/images/foo.png');

into

<script src="https://subdomain.cloudfront.net/assets/appname-342b0f87ea609e6d349c7925d86bd597.js">
background: url('https://subdomain.cloudfront.net/images/foo-735d6c098496507e26bb40ecc8c1394d.png');

You can disable fingerprinting in your ember-cli-build.js:

// ember-cli-build.js
var app = new EmberApp({
  fingerprint: {
    enabled: false
  }
});

Or remove the entry from your EmberApp and broccoli-asset-rev from your package.json.

Application Configuration

Application configurations from your ember-cli-build.js file will be stored inside a special meta tag in dist/index.html.

sample meta tag:

<meta name="user/config/environment" content="%7B%22modulePre.your.config">

This meta tag is required for your ember application to function properly. If you prefer to have this tag be part of your compiled javascript files instead, you may use the storeConfigInMeta flag in ember-cli-build.js.

// ember-cli-build.js
var app = new EmberApp({
  storeConfigInMeta: false
});

Configuring output paths

The compiled files are output to the following paths:

Assets Output File
app/index.html /index.html
app/*.js /assets/application-name.js
app/styles/app.css /assets/application-name.css
other CSS files in app/styles same filename in /assets
JavaScript files you import with app.import() /assets/vendor.js
CSS files you import with app.import() /assets/vendor.css

To change these paths, specify the outputPaths config option in ember-cli-build.js. The default setting is shown here:

// ember-cli-build.js
var app = new EmberApp({
  outputPaths: {
    app: {
      html: 'index.html',
      css: {
        'app': '/assets/application-name.css'
      },
      js: '/assets/application-name.js'
    },
    vendor: {
      css: '/assets/vendor.css',
      js: '/assets/vendor.js'
    }
  }
});

You may edit any of these output paths, but make sure to update your app.outputPaths.app.html, default it is index.html, and tests/index.html.

// ember-cli-build.js
var app = new EmberApp({
  outputPaths: {
    app: {
      js: '/assets/main.js'
    }
  }
});

The outputPaths.app.css option uses a key value relationship. The key is the input file and the value is the output location. Note that we do not include the extension for the input path, because each preprocessor has a different extension.

When using CSS preprocessing, only the app/styles/app.scss (or .less etc) is compiled. If you need to process multiple files, you must add another key:

// ember-cli-build.js
var app = new EmberApp({
  outputPaths: {
    app: {
      css: {
        'app': '/assets/application-name.css',
        'themes/alpha': '/assets/themes/alpha.css'
      }
    }
  }
});

Integration

When using Ember inside another project, you may want to launch Ember only when a specific route is accessed. If you’re preloading the Ember javascript before you access the route, you have to disable autoRun:

// ember-cli-build.js
var app = new EmberApp({
  autoRun: false
});

To manually run Ember: require("app-name/app")["default"].create({/* app settings */});

Subresource integrity

SRI calculation is done using the addon ember-cli-sri (which is included by default).

This plugin is used to generate SRI integrity for your applications. Subresource integrity is a security concept used to check JavaScript and stylesheets are loaded with the correct content when using a CDN.

Why

The reason to add this to your application is to protect against poisoned CDNs breaking JavaScript or CSS.

Customize

To customize SRI generation see: ember-cli-sri

Managing Dependencies

Ember CLI uses Bower for dependency management.

Bower Configuration

The Bower configuration file, bower.json, is located at the root of your Ember CLI project, and lists the dependencies for your project. Changes to your dependencies should be managed through this file, rather than manually installing packages individually.

Executing bower install will install all of the dependencies listed in bower.json in one step.

Ember CLI is configured to have git ignore your bower_components directory by default. Using the Bower configuration file allows collaborators to fork your repo and get their dependencies installed locally by executing bower install themselves.

Ember CLI watches bower.json for changes. Thus it reloads your app if you install new dependencies via bower install <dependencies> --save.

Further documentation about Bower is available at their official documentation page.

Compiling Assets

Ember CLI uses the Broccoli assets pipeline.

The assets manifest is located in the ember-cli-build.js file in your project root (not the default ember-cli-build.js).

To add an asset specify the dependency in yourember-cli-build.js before calling app.toTree(). You can only import assets that are within the bower_components or vendor directories. The following example scenarios illustrate how this works.

Javascript Assets

Standard Non-AMD Asset

First, provide the asset path as the first and only argument:

app.import('bower_components/moment/moment.js');

From here you would use the package as specified by its documentation, usually a global variable. In this case it would be:

import Ember from 'ember';
/* global moment */
// No import for moment, it's a global called `moment`

// ...
var day = moment('Dec 25, 1995');

Note: Don’t forget to make JSHint happy by adding a /* global MY_GLOBAL */ to your module, or by defining it within the predefs section of your .jshintrc file.

Alternatively, you could generate an ES6 shim to make the library accessible via import.

First, generate the shim:

ember generate vendor-shim moment

Next, provide the vendor asset path:

app.import('vendor/shims/moment.js');

Finally, use the package by adding the appropriate import statement:

import moment from 'moment';

// ...
var day = moment('Dec 25, 1995');
Standard AMD Asset

Provide the asset path as the first argument, and the list of modules and exports as the second:

app.import('bower_components/ic-ajax/dist/named-amd/main.js', {
  exports: {
    'ic-ajax': [
      'default',
      'defineFixture',
      'lookupFixture',
      'raw',
      'request',
    ]
  }
});

To use this asset in your app, import it. For example, with ic-ajax, when to use ic.ajax.raw:

import { raw as icAjaxRaw } from 'ic-ajax';
//...
icAjaxRaw( /* ... */ );
Environment Specific Assets

If you need to use different assets in different environments, specify an object as the first parameter. That object’s key should be the environment name, and the value should be the asset to use in that environment.

app.import({
  development: 'bower_components/ember/ember.js',
  production:  'bower_components/ember/ember.prod.js'
});

If you need to import an asset in one environment but not import it or any alternatives in other environments then you can wrap app.import in an if statement.

if (app.env === 'development') {
  app.import('vendor/ember-renderspeed/ember-renderspeed.js');
}
Customizing a built-in Asset

This is somewhat non-standard and discouraged, but suppose that due to a requirement in your application that you need to use the full version of Handlebars even in the production environment. You would simply provide the path to the EmberApp constructor:

var app = new EmberApp({
  vendorFiles: {
    'handlebars.js': {
      production: 'bower_components/handlebars/handlebars.js'
    }
  }
});

Alternatively, if you want to exclude the built-in asset from being automatically included in vendor.js, you can set its value to false:

var app = new EmberApp({
  vendorFiles: {
    'handlebars.js': false
  }
});

Note: The built-in assets are required dependencies needed by the environment to run your app. If you use the above method to specifically exclude some, you should still be including them in some other way.

Test Assets

You may have additional libraries that should only be included when running tests (such as qunit-bdd or sinon). These can be imported into your app in your ember-cli-build.js:

// ember-cli-build.js
var EmberApp = require('ember-cli/lib/broccoli/ember-app'),
    isProduction = EmberApp.env() === 'production';

var app = new EmberApp();

if ( !isProduction ) {
    app.import( app.bowerDirectory + '/sinonjs/sinon.js', { type: 'test' } );
    app.import( app.bowerDirectory + '/sinon-qunit/lib/sinon-qunit.js', { type: 'test' } );
}

module.exports = app.toTree();

Notes: - Be sure to pass { type: 'test' } as the second argument to app.import. This will ensure that your libraries are compiled into the test-support.js file.

Styles

Static CSS

Provide the asset path as the first argument:

app.import('bower_components/foundation/css/foundation.css');

All style assets added this way will be concatenated and output as /assets/vendor.css.

Dynamic Styles (SCSS, LESS, etc)

The vendor trees that are provided upon instantiation are available to your dynamic style files. Take the following example (in app/styles/app.scss):

@import "bower_components/foundation/scss/normalize.scss";

Other Assets

Using app.import()

All other assets like images or fonts can also be added via import(). By default, they will be copied to dist/ as they are.

app.import('bower_components/font-awesome/fonts/fontawesome-webfont.ttf');

This example would create the font file in dist/font-awesome/fonts/fontawesome-webfont.ttf.

You can also optionally tell import() to place the file at a different path. The following example will copy the file to dist/assets/fontawesome-webfont.ttf.

app.import('bower_components/font-awesome/fonts/fontawesome-webfont.ttf', {
  destDir: 'assets'
});

If you need to load certain dependencies before others, you can set the prepend property equal to true on the second argument of import(). This will prepend the dependency to the vendor file instead of appending it, which is the default behavior.

app.import('bower_components/es5-shim/es5-shim.js', {
  type: 'vendor',
  prepend: true
});
Using broccoli-funnel

With the broccoli-funnel package, (parts of) a bower-installed package can be used as assets as-is. First ensure that the Broccoli package needed to build is installed:

npm install broccoli-funnel --save-dev

Add this import to the top of ember-cli-build.js, just below the EmberApp require:

var Funnel = require('broccoli-funnel');

Within ember-cli-build.js, we merge assets from a bower dependency with the main app tree:

module.exports = function(defaults) {

   ...

   // Copy only the relevant files. For example the WOFF-files and stylesheets for a webfont:

   var extraAssets = new Funnel('bower_components/a-lovely-webfont', {
      srcDir: '/',
      include: ['**/*.woff', '**/stylesheet.css'],
      destDir: '/assets/fonts'
   });

   // Providing additional trees to the `toTree` method will result in those
   // trees being merged in the final output.

   return app.toTree(extraAssets);

}

In the above example the assets from the fictive bower dependency called a-lovely-webfont can now be found under /assets/fonts/, and might be linked to from index.html like so:

<link rel="stylesheet" href="assets/fonts/lovelyfont_bold/stylesheet.css">

You can exclude assets from the final output in a similar fashion. For example, to exclude all .gitkeep files from the final output:

// Again, add this import to the top of `ember-cli-build.js`, just below the `EmberApp` require:
var Funnel = require('broccoli-funnel');

// Normal ember-cli-build contents

// Filter toTree()'s output
var filteredAssets = new Funnel(app.toTree(), {
  // Exclude gitkeeps from output
  exclude: ['**/.gitkeep']
});

// Export filtered tree
module.exports = filteredAssets;

Note: broccoli-static-compiler is deprecated. Use broccoli-funnel instead.

Environments

Ember-CLI ships with support for managing your application’s environment. Ember-CLI will build an environment config file at config/environment. Here, you can define an ENV object for each environment (development, test and production). For now, this is limited to the three environments mentioned.

The ENV object contains two important keys: 1) EmberENV, and 2) APP. The first can be used to define Ember feature flags (see the Feature Flags guide). The second can be used to pass flags/options to your application instance.

You can access these environment variables in your application code by importing from ../config/environment or your-application-name/config/environment.

For example:

import ENV from 'your-application-name/config/environment';

if (ENV.environment === 'development') {
  // ...
}

Ember-CLI assigns ENV.EmberENV to window.EmberENV, which Ember reads on application initialization.

Additionally, Ember-CLI contains a number of environment-dependent helpers for assets:

It is now also possible to override command line options by creating a file in your app’s root directory called .ember-cli and placing desired overrides in it.

For example, a common desire is to change the port that ember-cli serves the app from. It’s possible to pass the port number directly to ember server in the command line, e.g. ember server --port 8080. If you wish to make this change a permanent configuration change, make the .ember-cli file and add the options you wish to pass to the server in a hash.

{
  "port": 8080
}

Deployments

You can easily deploy your Ember CLI application to a number of places using ember-cli-deploy. Or you can can follow some of the recipes below.

Heroku

Prerequistes:

Navigate to your Ember CLI application directory. Now, create your new Heroku application with the Ember CLI buildpack…

heroku create <OPTIONAL_APP_NAME> --buildpack https://github.com/tonycoco/heroku-buildpack-ember-cli.git

You should be able to now deploy your Ember CLI application with Heroku’s git hooks…

git commit -am "Empty commit for Heroku deployment" --allow-empty
git push heroku master

Need to make a custom nginx configuration change? No problem. In your Ember CLI application, add a config/nginx.conf.erb file. You can copy the existing configuration file and make your changes to it.

Azure

Continuous deployment with Azure Websites is enabled through Microsoft’s module ember-cli-azure-deploy. The installation is simple - just run the following commands in your Ember CLI app’s root directory:

npm install --save-dev -g ember-cli-azure-deploy
azure-deploy init

Next, set up your Azure Website’s source control to point to your repo - either via GitHub, BitBucket, VSO or any of the other available options. As soon as you push a new commit to your repository, Azure Websites will automatically run ember build and deploy the contents of the created dist directory to your website’s wwwroot.

Firebase

To deploy your Ember CLI application to Firebase, you’ll first need to enable hosting from your Firebase’s Dashboard. Then, install the Firebase Tools:

npm install -g firebase-tools

You can then configure your application for deployment by running the following in your app’s root directory and following the prompts:

firebase init

Finally, to deploy your application, run:

firebase deploy

For more configuration options, check out Firebase’s Hosting Guide.

History API and Base URL

If you are deploying the app to somewhere other than the root URL (/), you will need to configure the value of baseUrl in config/environment.js. For example

// config/environment.js
if (environment === 'production') {
  ENV.baseURL = '/path/to/ember/app/';
}

This value is used to set the value of base in index.html, e.g. <base href="/path/to/ember/app/" />, as this is required for the History API, and thus also the Router, to function correctly.

Content security policy

To enable the Content Security Policy on your production stack, you’ll need to copy the Content-Security-Policy and X-Content-Security-Policy (for IE) from the headers generated by ember server. If you’d like to enable it in report-only mode, use Content-Security-Policy-Report-Only and X-Content-Security-Policy-Report-Only. Make sure you’ve set a report-uri if you enable the CSP in report-only mode.

Deploying an HTTPS server using Nginx on a Unix/Linux/MacOSx machine

The following is a simple deployment with https using nginx. Http just redirects to the https server here. Don’t forget to include your ssl keys in your config.

Before deployment make sure you run this command to populate the dist directory:

ember build --environment="production"

File: nginx.conf

## Nginx Production Https Ember Server Configuration

## https site##
server {
    listen      443 default;
    server_name <your-server-name>;
    #root        /usr/share/nginx/html;
    root        <root path to an ember /dist directory>;
    index       index.html index.htm;

    # log files
    access_log  /var/log/nginx/<your-server-name>.access.log;
    error_log   /var/log/nginx/<your-server-name>.error.log;

    # ssl files
    ssl on;
    keepalive_timeout   60;

    # include information on SSL keys, cert, protocols and ciphers
    # SSLLabs.com is a great resource for this, along with testing
    # your SSL configuration: https://www.ssllabs.com/projects/documentation/

    # proxy buffers
    proxy_buffers 16 64k;
    proxy_buffer_size 128k;

    ## default location ##
    location / {
        include /etc/nginx/mime.types;
        try_files $uri $uri/ /index.html?/$request_uri;
    }

}

## http redirects to https ##
server {
    listen      80;
    server_name <your-server-name>;

    # Strict Transport Security
    add_header Strict-Transport-Security max-age=2592000;
    rewrite ^/.*$ https://$host$request_uri? permanent;
}

Upgrading

Upgrading an Ember CLI App

Steps to upgrade to the latest version of Ember CLI are included with each release, but these are the common steps one would follow to update Ember CLI using NPM from within your project directory.

Setup

  • Remove old global ember-cli
    npm uninstall -g ember-cli
    
  • Clear NPM cache
    npm cache clean
    
  • Clear Bower cache
    bower cache clean
    
  • Install a new global ember-cli, replacing X.X.X with the version of ember-cli you want to install
    npm install -g ember-cli@X.X.X
    

Project Update

  • Delete temporary development directories
    rm -rf node_modules bower_components dist tmp
    
  • Update your project’s package.json file to use the latest version of ember-cli, replacing X.X.X with the version of ember-cli you want to install
    npm install ember-cli@X.X.X --save-dev
    
  • Reinstall NPM and Bower dependencies
    npm install
bower install
    
  • Run the new project blueprint on your projects directory. Please follow the prompts, and review all changes (tip: you can see a diff by pressing d).
    ember init
    

The most common sources of upgrade pain are not clearing out old packages in the first step of the project update and missing a change in the last step of the project update. Please review each change from the last step carefully to ensure you both have not missed a change from the upgrade and that you have not accidentally removed code you may have added to your project during your work.

When the upgrade process has completed, you should be able to issue the ember -v command and see that the version: noted in the resulting output matches the version you just upgraded to.

Common Issues

Content security policy

Ember CLI comes bundled with the ember-cli-content-security-policy addon which enables the Content Security Policy in modern browsers when running the development server.

The default header sent by the addon sends a policy where only content from 'self' is allowed. This means that by default, the browser will restrict your app from loading assets and data outside of localhost:4200 or doing any inline style or script modifications. If your app does any of these, you’ll see a lot of these errors:

Refused to execute inline script because it violates the following Content Security Policy directive: ...

You can get rid of these errors by modifing the CSP for your app. This is described in the addon readme.

npm package management with sudo

Installing packages such as bower with sudo powers can lead to permissions issues and ultimately to problems installing dependencies.

For example

Uncaught Error: Could not find module ember/resolver loader/loader.js:42

can be caused by installing bower with sudo. See https://gist.github.com/isaacs/579814 for a collection of various solutions.

Installing from behind a proxy

If you’re behind a proxy, you might not be able to install because ember-cli — or some of its dependencies — tries to git clone a git:// url. (In this scenario, only http:// urls will work).

You’ll probably get an error like this:

npm ERR! git clone git://github.com/jgable/esprima.git Cloning into bare repository '/home/<username>/.npm/_git-remotes/git-github-com-jgable-esprima-git-d221af32'...
npm ERR! git clone git://github.com/jgable/esprima.git
npm ERR! git clone git://github.com/jgable/esprima.git fatal: unable to connect to github.com:
npm ERR! git clone git://github.com/jgable/esprima.git github.com[0: 192.30.252.129]: errno=Connection timed out
npm ERR! Error: Command failed: fatal: unable to connect to github.com:
npm ERR! github.com[0: 192.30.252.129]: errno=Connection timed out

This is not a ember-cli issue per se, but here’s a workaround. You can configure git to make the translation:

git config --global url."https://".insteadOf git://

Using canary build instead of release

In bower.json instead of a version number use:

"ember": "components/ember#canary",

And, following dependencies add resolutions:

"resolutions": {
  "ember": "canary"
}

This can also be applied to Ember Data:

"ember-data": "components/ember-data#canary",

And, adding to resolutions:

"resolutions": {
  "ember-data": "canary"
}

Wipe your vendor directory clean then run npm install && bower install.

Removing default ember-cli libraries

  • To use ember-cli without Ember Data

npm rm ember-data --save-dev

  • To use ember-cli without ember-ajax

npm rm ember-ajax --save-dev

  • To reinstall latest Ember Data version

npm update ember-data

Many Broccoli plugins and Ember CLI addons can use symlinks to speedup the build process. When working on the Windows platform there are some caveats involved in making sure Ember CLI and other plugins can use symlinks. If symlinks are not available plugins should fall back to copying files. However the speed benefits of symlinking are substantial, so it is worth the effort to make sure Ember CLI can take advantage of them.

In order to create symlinks the account running Ember CLI must have the SeCreateSymbolicLinkPrivilege. Users in the Administrators group have this permission already. However if UAC (User Access Control) is enabled users in the Administrators group must run their shell using Run As Administrator. This is because UAC strips away certain permissions from the Administrators group, including SeCreateSymbolicLinkPrivilege.

Run As Administrator

If the user account is not part of the Administrators group you will need to add the SeCreateSymbolicLinkPrivilege in order to allow the creation of symlinks. To do this open the Local Security Policy by typing Local Security Policy in the Run Box.

Under Local Policies -> User Rights Assignment find the Create symbolic links policy and double click it to add a new user or group. Once you add your user or group has been added your user should be able to create symlinks. Keep in mind if your user is part of the Administrators group and UAC is enabled you will still need to start your shell using Run as Administrator.

Enabling Symlinks

PhantomJS on Windows

When running tests on Windows via PhantomJS the following error can occur:

events.js:72
throw er; // Unhandled 'error' event
^
Error: spawn ENOENT
at errnoException (child_process.js:988:11)
at Process.ChildProcess._handle.onexit (child_process.js:779:34)

In order to fix this ensure the following is added to your PATH:

C:\Users\USER_NAME\AppData\Roaming\npm\node_modules\phantomjs\lib\phantom

Cygwin on Windows

When running ember cli command within cygwin the following error can occur:

net.js:156 this._handle.open(options.fd); ^ Error: EINVAL, invalid argument at new Socket (net.js:156:18) at process.stdin (node.js:664:19)

Try to launch cygwin using the following command: C:\cygwin\bin\bash.exe –login -i -c “cd /cygdrive/c/Users/username/; exec bash”

Usage with Vagrant

Vagrant is a system for automatically creating and setting up development environments that run in a virtual machine (VM).

Running your ember-cli development environment from inside of a Vagrant VM will require some additional configuration and will carry a few caveats.

Ports

In order to access your ember-cli application from your desktop’s web browser, you’ll have to open some forwarded ports into your VM. The default ports that ember-cli uses are 4200 and 35729 for its internal web server and livereload, respectively:

Vagrant.configure("2") do |config|
  # ...
  config.vm.network "forwarded_port", guest: 4200, host: 4200
  config.vm.network "forwarded_port", guest: 35729, host: 35729
end

Watched Files

The way Vagrant syncs directories between your desktop and the VM will break the default mechanism ember-cli uses to watch files and cause issues when updates are subsequently compiled. To restore this functionality, you’ll have to make two changes:

  1. Fall back to polling when invoking the serve command: ember serve --watcher polling.

  2. Use nfs for synced folders.

VM Setup

When setting up your VM, install ember-cli dependencies as you normally would. If you’ve already run ember install in your project’s directory from your host machine, you’ll have to delete the node_modules directory and re-install those dependencies from the VM. This is particularly necessary if you have node dependencies that use native libraries (e.g., broccoli-sass, which uses the libsass C library).

Provider

The two most common Vagrant providers, VirtualBox and VMware Fusion, will both work. However, VMware Fusion is substantially faster and will use less battery life if you’re on a laptop. As of now, VirtualBox will use 100% of a single CPU core to poll for file system changes inside of the VM.

Broken Glob npm package issue

The glob package is required by many of ember-cli packages, however there is a version mismatch between various includes which currently is an issue.

undefined is not a function
TypeError: undefined is not a function
    at rimraf (/home/username/emberApp/node_modules/ember-cli/node_modules/broccoli-caching-writer/node_modules/rimraf/rimraf.js:57:13)
    at lib$rsvp$node$$tryApply (/home/username/emberApp/node_modules/ember-cli/node_modules/broccoli-caching-writer/node_modules/rsvp/dist/rsvp.js:1467:11)
    at lib$rsvp$node$$handleValueInput (/home/username/emberApp/node_modules/ember-cli/node_modules/broccoli-caching-writer/node_modules/rsvp/dist/rsvp.js:1567:20)
    at fn (/home/username/emberApp/node_modules/ember-cli/node_modules/broccoli-caching-writer/node_modules/rsvp/dist/rsvp.js:1555:18)
    at /home/username/emberApp/node_modules/ember-cli/node_modules/broccoli-caching-writer/index.js:100:14
    at lib$rsvp$$internal$$tryCatch (/home/username/emberApp/node_modules/ember-cli/node_modules/promise-map-series/node_modules/rsvp/dist/rsvp.js:489:16)
    at lib$rsvp$$internal$$invokeCallback (/home/username/emberApp/node_modules/ember-cli/node_modules/promise-map-series/node_modules/rsvp/dist/rsvp.js:501:17)
    at lib$rsvp$$internal$$publish (/home/username/emberApp/node_modules/ember-cli/node_modules/promise-map-series/node_modules/rsvp/dist/rsvp.js:472:11)
    at lib$rsvp$asap$$flush (/home/username/emberApp/node_modules/ember-cli/node_modules/promise-map-series/node_modules/rsvp/dist/rsvp.js:1290:9)
    at process._tickCallback (node.js:355:11)

To fix the issue there are two solutions:

  • Update to ember-cli@0.2.0
  • Lock rimraf@2.2.8 and glob@4.0.5

Locking package versions

Adding dependency versions into your package.json fixes the dependency issue:

"dependencies": {
  "glob": "4.0.5",
  "rimraf": "2.2.8"
},
"bundledDependencies": [
  "glob",
  "rimraf"
]
...

Clear out old packages and reinstall them with the following:

rm -rf node_modules; npm cache clean; npm install;

Windows

Windows

Improve and Optimize Build Performance

Build times on Windows are longer than on Linux or Mac OS X. Much of that penalty is not because of node or ember-cli, but because of Windows services monitoring your filesystem. Microsoft wrote a configuration tool as well as an Ember Addon to automatically configure Windows to optimize build performance. The automatic configuration instructs Windows Search and Windows Defender to ignore Ember Cli’s tmp directory.

*Remember to always open up PowerShell/CMD with elevated privileges (“run as Administrator”).

Some have found success in doing a system cleanup with tools such as ccleaner. Clean out temp files, recycle bin, memory dumps, old prefetch data, etc. Additionally, do a registry cleanup to fix potentially issues that might indirectly impact tools. While these side-effects aren’t clearly understood yet, it shouldn’t hurt and should generally aid overall system performance.

Ember Addon

The addon has the benefit of being shippable with your project, meaning that other developers on the project do not need to install anything to use the automatic configuration. To install the addon, run the following in the root of your project directory:

npm install --save-dev ember-cli-windows-addon

Then, to start the automatic configuration, run:

ember windows
Node Cli Tool

The automatic configuration tool can also be installed directly, making it available in PowerShell & CMD. To install, run:

npm install ember-cli-windows -g

Once the tool is installed, you can run it in any Ember Cli project directory.

ember-cli-windows

Additional performance can be gained by using an elevated prompt, which can be achieved by starting PowerShell or CMD ‘as Administrator’. If you do not have administrative rights on your machine, see the section on symlinks below for information on how to enable additional performance gains.

Issues With npm: EEXISTS, Path too Long, etc

There were always two major issues with running Node.js on Windows: First and foremost, the operating system maintains a maximum length for path names, which clashes with Node’s traditional way of nesting modules in node_modules. The second issue was a bit more subtle: The npm installer had a set of steps it executed for each package and it would immediately start executing them as soon as it decided to act on a package, resulting in hard-to-debug race conditions.

Npm@3 is a nearly complete rewrite of npm, fixing both issues. Windows users of Ember Cli might want to make the switch to npm@3 early, to benefit from its flat module installation (solving any issues involving long path names) as well as its multi-stage installer.

The new version is currently still in beta - and while performing extremely well so far, you might still run into issues. To easily up- and downgrade between versions, use Microsoft’s npm-windows-upgrade tool, which automates the upgrade and also allows easy downgrades to older versions.

Editors

Atom

If you are using Atom with ember-cli, there are some packages available specific to Ember development.

Atom -> Preferences -> Install

Emacs

If you are using Emacs with ember-cli, Emacs creates temporary backup, autosave, and lockfiles that interfere with broccoli watcher, so they need to either be moved out of the way or disabled. To do that, ensure your emacs configuration contains the following:

(setq backup-directory-alist `((".*" . ,temporary-file-directory)))
(setq auto-save-file-name-transforms `((".*" ,temporary-file-directory t)))
(setq create-lockfiles nil)

An ember-mode package is also available. It has shortcuts for quickly navigating files in ember projects, running generators, and running build, serve, and test tasks. It also includes support for linking build errors to files and minibuffer notifications of ember serve status. It can be installed from MELPA. To use MELPA, ensure your configuration contains the following:

(require 'package)
(add-to-list 'package-archives
             '("melpa" . "http://melpa.org/packages/") t)
(package-initialize)

Then ember-mode can be installed from the package menu at M-x package-list-packages. After it is installed, add a file named .dir-locals.el to the root of your ember projects with the contents:

((nil . ((mode . ember))))

to enable it inside those projects.

Sublime Text

If you are using Sublime Text with ember-cli, by default it will try to index all files in your tmp directory for its GoToAnything functionality. This will cause your computer to come to a screeching halt @ 90%+ CPU usage, and can significantly increase build times. Simply remove these directories from the folders Sublime Text watches:

Sublime Text -> Preferences -> Settings - User

// folder_exclude_patterns and file_exclude_patterns control which files
// are listed in folders on the side bar. These can also be set on a per-
// project basis.
"folder_exclude_patterns": [".svn", ".git", ".hg", "CVS", "tmp/class-*", "tmp/es_*", "tmp/jshinter*", "tmp/replace_*", "tmp/static_compiler*", "tmp/template_compiler*", "tmp/tree_merger*", "tmp/coffee_script*", "tmp/concat-tmp*", "tmp/export_tree*", "tmp/sass_compiler*"]

WebStorm

If you are using WebStorm with ember-cli, you will need to modify your .gitignore file, enable ECMAScript6 settings, and mark certain directories.

First, add the following line to .gitignore:

.idea

Next, from the WebStorm menu:

File > Settings -> Languages & Frameworks -> JavaScript -> ECMAScript6

Click ‘OK’ to close the Settings modal window.

Next, in Webstorm’s Project window right-click on each of the following directories, go to ‘Mark Directory As’ and mark as indicated:

Mark as Excluded:

/tmp
/dist

Mark as Resource Root:

/
/bower_components
/bower_components/ember-qunit/lib
/public

Mark as Test Sources Root:

/tests

Intellij-emberjs

This plugin provides excellent Ember.js support for all JetBrains IDEs that support JavaScript, including WebStorm.

In order to install it, go to File | Settings... | Plugins | Browse repositories... search for Ember.js and hit the Install button.