Recommended way to include bootstrap library in Ember.JS ember-cli App
Twitter Bootstrapember.jsBowerEmber CliTwitter Bootstrap Problem Overview
I am trying to install properly Twitter Bootstrap in my current ember-cli project. I did install bootstrap with bower :
bower install --save bootstrap
Now the library is downloded in /vendor/bootstrap/dist/(css|js|fonts) I tried what is mentioned here : http://ember-cli.com/#managing-dependencies replacing path and css files names but I get errors regarding the Brocfile.js file. I think the brocfile format has changed too much compared to the example.
I also tried to @import with the /app/styles/app.css file after moving the stylesheets in the /app/styles/ directory :
@import url('/assets/bootstrap.css');
@import url('/assets/bootstrap-theme.css');
But it did not work. The files are visible true dev server : http://localhost:4200/assets/bootstrap.css
Can someone throw me a bone here ?
Thx
Edit :
ember -v
ember-cli 0.0.23
brocfile.js
/* global require, module */
var uglifyJavaScript = require('broccoli-uglify-js');
var replace = require('broccoli-replace');
var compileES6 = require('broccoli-es6-concatenator');
var validateES6 = require('broccoli-es6-import-validate');
var pickFiles = require('broccoli-static-compiler');
var mergeTrees = require('broccoli-merge-trees');
var env = require('broccoli-env').getEnv();
var getEnvJSON = require('./config/environment');
var p = require('ember-cli/lib/preprocessors');
var preprocessCss = p.preprocessCss;
var preprocessTemplates = p.preprocessTemplates;
var preprocessJs = p.preprocessJs;
module.exports = function (broccoli) {
var prefix = 'caisse';
var rootURL = '/';
// index.html
var indexHTML = pickFiles('app', {
srcDir: '/',
files: ['index.html'],
destDir: '/'
});
indexHTML = replace(indexHTML, {
files: ['index.html'],
patterns: [{ match: /\{\{ENV\}\}/g, replacement: getEnvJSON.bind(null, env)}]
});
// sourceTrees, appAndDependencies for CSS and JavaScript
var app = pickFiles('app', {
srcDir: '/',
destDir: prefix
});
app = preprocessTemplates(app);
var config = pickFiles('config', { // Don't pick anything, just watch config folder
srcDir: '/',
files: [],
destDir: '/'
});
var sourceTrees = [app, config, 'vendor'].concat(broccoli.bowerTrees());
var appAndDependencies = mergeTrees(sourceTrees, { overwrite: true });
// JavaScript
var legacyFilesToAppend = [
'jquery.js',
'handlebars.js',
'ember.js',
'ic-ajax/dist/named-amd/main.js',
'ember-data.js',
'ember-resolver.js',
'ember-shim.js',
'bootstrap/dist/js/bootstrap.js'
];
var applicationJs = preprocessJs(appAndDependencies, '/', prefix);
applicationJs = compileES6(applicationJs, {
loaderFile: 'loader/loader.js',
ignoredModules: [
'ember/resolver',
'ic-ajax'
],
inputFiles: [
prefix + '/**/*.js'
],
legacyFilesToAppend: legacyFilesToAppend,
wrapInEval: env !== 'production',
outputFile: '/assets/app.js'
});
if (env === 'production') {
applicationJs = uglifyJavaScript(applicationJs, {
mangle: false,
compress: false
});
}
// Styles
var styles = preprocessCss(appAndDependencies, prefix + '/styles', '/assets');
// Bootstrap Style integration
var bootstrap = pickFiles('vendor', {
srcDir: '/bootstrap/dist/css',
files: [
'bootstrap.css',
'bootstrap-theme.css'
],
destDir: '/assets/'
});
//var bootstrap = preprocessCss(appAndDependencies, '/vendor/bootstrap/dist/css', '/assets');
// Ouput
var outputTrees = [
indexHTML,
applicationJs,
'public',
styles,
bootstrap
];
// Testing
if (env !== 'production') {
var tests = pickFiles('tests', {
srcDir: '/',
destDir: prefix + '/tests'
});
var testsIndexHTML = pickFiles('tests', {
srcDir: '/',
files: ['index.html'],
destDir: '/tests'
});
var qunitStyles = pickFiles('vendor', {
srcDir: '/qunit/qunit',
files: ['qunit.css'],
destDir: '/assets/'
});
testsIndexHTML = replace(testsIndexHTML, {
files: ['tests/index.html'],
patterns: [{ match: /\{\{ENV\}\}/g, replacement: getEnvJSON.bind(null, env)}]
});
tests = preprocessTemplates(tests);
sourceTrees = [tests, 'vendor'].concat(broccoli.bowerTrees());
appAndDependencies = mergeTrees(sourceTrees, { overwrite: true });
var testsJs = preprocessJs(appAndDependencies, '/', prefix);
var validatedJs = validateES6(mergeTrees([app, tests]), {
whitelist: {
'ember/resolver': ['default'],
'ember-qunit': [
'globalize',
'moduleFor',
'moduleForComponent',
'moduleForModel',
'test',
'setResolver'
]
}
});
var legacyTestFiles = [
'qunit/qunit/qunit.js',
'qunit-shim.js',
'ember-qunit/dist/named-amd/main.js'
];
legacyFilesToAppend = legacyFilesToAppend.concat(legacyTestFiles);
testsJs = compileES6(testsJs, {
// Temporary workaround for
// https://github.com/joliss/broccoli-es6-concatenator/issues/9
loaderFile: '_loader.js',
ignoredModules: [
'ember/resolver',
'ember-qunit'
],
inputFiles: [
prefix + '/**/*.js'
],
legacyFilesToAppend: legacyFilesToAppend,
wrapInEval: true,
outputFile: '/assets/tests.js'
});
var testsTrees = [qunitStyles, testsIndexHTML, validatedJs, testsJs];
outputTrees = outputTrees.concat(testsTrees);
}
return mergeTrees(outputTrees, { overwrite: true });
};
Twitter Bootstrap Solutions
Solution 1 - Twitter Bootstrap
BASH:
bower install --save bootstrap
Brocfile.js:
app.import('vendor/bootstrap/dist/js/bootstrap.js');
app.import('vendor/bootstrap/dist/css/bootstrap.css');
The JS will be added to the app.js, which is linked by default, and the CSS will be added to assets/vendor.css
, which as of May 14th, is also added by default.
For reference: http://www.ember-cli.com/#managing-dependencies
In response to @Joe's question surrounding fonts and other assets, I was unable to get the recommended app.import() method to work on the fonts. I instead opted for the merge-trees and static-compiler approach:
var mergeTrees = require('broccoli-merge-trees');
var pickFiles = require('broccoli-static-compiler');
var extraAssets = pickFiles('vendor/bootstrap/dist/fonts',{
srcDir: '/',
files: ['**/*'],
destDir: '/fonts'
});
module.exports = mergeTrees([app.toTree(), extraAssets]);
Solution 2 - Twitter Bootstrap
BASH:
bower install --save bootstrap
Brocfile.js:
/* global require, module */
...
app.import('bower_components/bootstrap/dist/css/bootstrap.css');
app.import('bower_components/bootstrap/dist/css/bootstrap.css.map', {
destDir: 'assets'
});
app.import('bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.eot', {
destDir: 'fonts'
});
app.import('bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf', {
destDir: 'fonts'
});
app.import('bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.svg', {
destDir: 'fonts'
});
app.import('bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff', {
destDir: 'fonts'
});
app.import('bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2', {
destDir: 'fonts'
});
app.import('bower_components/bootstrap/dist/js/bootstrap.js');
module.exports = app.toTree();
Solution 3 - Twitter Bootstrap
You might want to check out ember-bootstrap, which will import the bootstrap assets automatically.
ember install ember-bootstrap
Moreover it adds a suite of native ember components to your app, that make working with bootstrap features much easier in ember. Check it out, although I am a bit biased, as I am the author of it! ;)
Solution 4 - Twitter Bootstrap
Update 3/30/15
plus ça change... I use ember-cli-bootstrap-sassy now, it seems to bring along minimum cruft while still letting me customize Bootstrap's variables.
Update 1/22/15
You should probably use Johnny's solution above instead of the lib I originally mentioned. I also like ember-cli-bootstrap-sass, because I can customize Bootstrap's variables directly in my project.
Original 7/11/14
If you're using a version of ember-cli that supports addons (0.35+, I believe), you can now use the ember-cli-bootstrap package. From the root of your app,
npm install --save-dev ember-cli-bootstrap
That's it!
> Note: as @poweratom points out, ember-cli-bootstrap
is somebody else's library which chooses to also include bootstrap-for-ember. Thus, this lib could get out of sync with official bootstrap version. However, I still find it a great way to get prototyping fast on a new project!
Solution 5 - Twitter Bootstrap
$> bower install --save bootstrap
Afterwards add following two lines to your ember-cli-builds.js (or Brocfile.js if you are using an older version of Ember.js):
app.import(app.bowerDirectory + '/bootstrap/dist/js/bootstrap.js');
app.import(app.bowerDirectory + '/bootstrap/dist/css/bootstrap.css');
And voilà, ready to go!
updated 08/18/2015: adapted to new scheme introduced in Ember.js 1.13
Solution 6 - Twitter Bootstrap
This is how I package vendor CSS files with Broccoli (which underpins Ember-cli).
var vendorCss = concat('vendor', {
inputFiles: [
'pikaday/css/pikaday.css'
, 'nvd3/nv.d3.css'
, 'semantic-ui/build/packaged/css/semantic.css'
]
, outputFile: '/assets/css/vendor.css'
});
Where the vendor
folder is where my Bower packages live. And assets
is where I'm expecting my CSS to live. I'm assuming you've installed Bootstrap using Bower, which is the Ember-cli way.
Then in my index.html, I'm simply referencing that vendor.css
file:
<link href="/assets/css/vendor.css" rel="stylesheet" type="text/css" media="all">
Cheers.
Solution 7 - Twitter Bootstrap
If you're using SASS (probably via ember-cli-sass
), bower_components
is automatically added to the lookup path. This means you can just use Bower and avoid the Brocfile/ember-cli-build file altogether.
Install the official SASS version of Bootstrap with Bower
bower install --save bootstrap-sass
then import the lib in app.scss
. The nice thing about this is you can customize the variables before importing bootstrap:
$brand-primary: 'purple';
@import 'bower_components/bootstrap-sass/assets/stylesheets/bootstrap';
Solution 8 - Twitter Bootstrap
bower install --save bootstrap
in your brocfile.js
:
app.import('bower_components/bootstrap/dist/js/bootstrap.js');
app.import('bower_components/bootstrap/dist/css/bootstrap.css');
Solution 9 - Twitter Bootstrap
On the terminal (For those using Node Package Manager)
npm install bootstrap --save
Using ember-cli, to import your installed bootstrap
Open the ember-cli-build.js
file
module.exports = function(defaults) {
let app = new EmberApp(defaults, {
// Add options here
});
app.import('node_modules/bootstrap/dist/css/bootstrap.min.css');
app.import('node_modules/bootstrap/dist/js/bootstrap.min.js');
That will do it if bootstrap is installed via the NPM installer.
Do not do this:
app.import('./node_modules/bootstrap/dist/css/bootstrap.min.css');
app.import('./node_modules/bootstrap/dist/js/bootstrap.min.js');