Asset Compilation

Raw Assets

  • public/assets vs app/styles

To add images, fonts, or other assets, place them in the public/assets folder. 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 Brocfile. 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 Brocfile. To enable or disable JS minification you may supply a boolean value for minifyJS:enabled.

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 --save-dev bootstrap

In Brocfile.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

  • Relative pathing gets changed (how to customize?)
  • @import statements -> concat

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.

npm install --save-dev ember-cli-less

Sass

To enable Sass, you’ll need to add broccoli-sass to your NPM modules (both .scss/.sass are allowed as of broccoli-sass > 0.2.0).

npm install --save-dev broccoli-sass

Compass

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

npm install --save-dev ember-cli-compass-compiler

Stylus

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

npm install --save-dev ember-cli-stylus

CoffeeScript

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

npm install --save-dev 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:

1 # app/models/post.coffee
2 `import Ember from 'ember'`
3 `import User from 'appkit/models/user'`
4 
5 Post = Ember.Object.extend
6   init: (userId) ->
7     @set 'user', User.findById(userId)
8 
9 `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 --save-dev broccoli-ember-script

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:

npm install --save-dev broccoli-emblem-compiler

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 Brocfile.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.
  • extensions - Default: ['js', 'css', 'png', 'jpg', 'gif'] - 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.

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

1 var app = new EmberApp({
2   fingerprint: {
3     exclude: ['fonts/169929'],
4     prepend: 'https://sudomain.cloudfront.net/'
5   }
6 });

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 Brocfile.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 Brocfile.js 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.

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 you can edit the outputPaths config option. The default setting is shown here:

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.index, default it is index.html, and tests/index.html.

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:

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