Ember CLI uses Bower for dependency management.
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 --save <dependencies>
.
Further documentation about Bower is available at their official documentation page.
In your Brocfile.js
specify a dependency 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.
Provide the asset path as the first and only argument:
1 app.import('bower_components/moment/moment.js');
From here you would use the package as specified by it’s documentation, usually a global variable. In this case it would be:
1 import Ember from 'ember';
2 /* global moment */
3 // No import for moment, it's a global called `moment`
4
5 // ...
6 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.
Provide the asset path as the first argument, and the list of modules and exports as the second:
1 app.import('bower_components/ic-ajax/dist/named-amd/main.js', {
2 exports: {
3 'ic-ajax': [
4 'default',
5 'defineFixture',
6 'lookupFixture',
7 'raw',
8 'request',
9 ]
10 }
11 });
To use this asset in your app, import it.
For example, with ic-ajax
, when to use ic.ajax.raw
:
1 import { raw as icAjaxRaw } from 'ic-ajax';
2 //...
3 icAjaxRaw( /* ... */ );
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.
1 app.import({
2 development: 'bower_components/ember/ember.js',
3 production: 'bower_components/ember/ember.prod.js'
4 });
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.
1 if (app.env === 'development') {
2 app.import('vendor/ember-renderspeed/ember-renderspeed.js');
3 }
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:
1 var app = new EmberApp({
2 vendorFiles: {
3 'handlebars.js': {
4 production: 'bower_components/handlebars/handlebars.js'
5 }
6 }
7 });
You may have additional libraries that should only be included when running tests (such as qunit-bdd or sinon). These can be merged into your assets in your Brocfile.js:
1 var EmberApp = require('ember-cli/lib/broccoli/ember-app');
2 var pickFiles = require('broccoli-static-compiler');
3
4 var app = new EmberApp();
5
6 var qunitBdd = pickFiles('bower_components/qunit-bdd/lib', {
7 srcDir: '/',
8 files: ['qunit-bdd.js'],
9 destDir: '/assets'
10 });
11
12 module.exports = app.toTree(qunitBdd);
Notes:
- Be sure to add the appropriate script tag for your test library.
- The first argument to pickFiles
is a tree. This means that doing pickFiles('bower_components', ...)
will cause all files in /bower_components
to be watched. If you get a Error: watch EMFILE
during build, this could be the culprit. Consider using a more specific path as tree or use pickFiles(unwatchedTree('bower_components'),...)
from broccoli-unwatched-tree
.
...
<script src="assets/qunit.js"></script>
<script src="assets/qunit-bdd.js"></script>
...
Provide the asset path as the first argument:
1 app.import('bower_components/foundation/css/foundation.css');
All style assets added this way will be concatenated and output as /assets/vendor.css
.
The vendor trees that are provided upon instantiation are available to your dynamic style files. Take the following example (in app/styles/app.scss
):
1 @import "bower_components/foundation/scss/normalize.scss";
All other assets like images or fonts can also be added via import()
. By default, they
will be copied to dist/
as they are.
1 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
.
1 app.import('bower_components/font-awesome/fonts/fontawesome-webfont.ttf', {
2 destDir: 'assets'
3 });
With the broccoli-static-compiler package, (parts of) a bower-installed package can be used as assets as-is. First ensure that the Broccoli package needed to build are installed:
npm install --save-dev broccoli-static-compiler
Add this import to the top of Brocfile.js
, just below the EmberApp
require:
1 var pickFiles = require('broccoli-static-compiler');
At the bottom of Brocfile.js
we merge assets from a bower dependency with the main app tree:
1 // Remove this line:
2 // module.exports = app.toTree()
3
4 // Copy only the relevant files. For example the WOFF-files and stylesheets for a webfont:
5 var extraAssets = pickFiles('bower_components/a-lovely-webfont', {
6 srcDir: '/',
7 files: ['**/*.woff', '**/stylesheet.css'],
8 destDir: '/assets/fonts'
9 });
10
11 // Providing additional trees to the `toTree` method will result in those
12 // trees being merged in the final output.
13 module.exports = 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">