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 });
};
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]);
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();
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! ;)
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!
$> 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
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';
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.
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');
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');
I'm using ember-bootstrap add-on which is working fine but I would like to use the Cerulean theme from https://bootswatch.com/cerulean/. If I just overwrite the .CSS files in bower_components/bootstrap/dist/css then I expect they will be overwritten the next time I do a bower install or upgrade ember. How do I get around that please?
First of all you need to manually install bootstrap:
$ bower install bootstrap --save
Then edit ember-cli-build.js so it looks like that:
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
module.exports = function(defaults) {
var app = new EmberApp(defaults, {
// If you do not use ember-bootstrap - then you can omit these lines
'ember-bootstrap': {
'importBootstrapCSS': false
}
});
app.import(app.bowerDirectory + '/bootstrap/dist/css/bootstrap.css');
app.import(app.bowerDirectory + '/bootstrap/dist/js/bootstrap.js');
app.import(app.bowerDirectory + '/bootstrap/dist/fonts/glyphicons-halflings-regular.woff', {
destDir: 'fonts'
});
return app.toTree();
};
Now you have fully working bootstrap. To add Celurian theme copy its bootstrap.css to vendor/ directory.
Then remove original bootstrap.css from ember-cli-build.js and add theme css:
module.exports = function(defaults) {
var app = new EmberApp(defaults, {
// If you do not use ember-bootstrap - then you can omit these lines
'ember-bootstrap': {
'importBootstrapCSS': false
}
});
//app.import(app.bowerDirectory + /bootstrap/dist/css/bootstrap.css');
// The name does not matter, default bootstrap.css will work as well
app.import('vendor/celurian.css');
app.import(app.bowerDirectory + '/bootstrap/dist/js/bootstrap.js');
app.import(app.bowerDirectory + '/bootstrap/dist/fonts/glyphicons- halflings-regular.woff', {
destDir: 'fonts'
});
return app.toTree();
};
So, in essence, you need to add required files to vendor directory and import them in ember-cli-build.js.
The other way would be to use SASS and just import required files from app.scss.
I am trying to make my addon supply vendor'd data to the app using it. The library is CKEditor (a customized version generated from the CKEditor builder).
I know I can use the addon blueprint to add a bower dependency but since CKEditor is customized I can't use bower to download that same version in the consuming app.
I've used the treeForPublic and broccoli funnel to copy from my addon vendor folder the whole ckeditor folder to the app public folder (this is required by ckeditor).
My only issue is that the consuming app also needs to have the ckeditor folder in its vendor folder or it won't build because the watcher can't find it.
I was with the impression that if the addon was moving the folder to the public destination and was also importing js/css files in the included hook the original vendor'd folder was not needed by the final app.
Have I understood it wrong or can I do this without duplicating my ckeditor folder between the addon and the app ?
here is what I have so far :
included: function(app) {
this._super.included(app);
app.import('vendor/ckeditor_custom/ckeditor.js');
app.import('vendor/ckeditor_custom/styles.js');
app.import('vendor/ckeditor_custom/lang/fr.js');
app.import('vendor/ckeditor_custom/skins/minimalist/editor.css');
},
contentFor: function(type, config) {
if (type === 'vendor-prefix') {
return "window.CKEDITOR_BASEPATH = 'assets/ckeditor/';";
}
},
treeForPublic: function (tree) {
var ckeditorTree = new Funnel('vendor/ckeditor_custom/', {
srcDir: '/',
exclude: ['**/.DS_Store','**/*.md'],
destDir: 'assets/ckeditor'
});
return BroccoliMergeTrees([tree, ckeditorTree]);
},
treeForVendor: function (tree) {
var ckeditorTree = new Funnel('vendor/ckeditor_custom/', {
srcDir: '/',
exclude: ['**/.DS_Store','**/*.md'],
destDir: 'ckeditor_custom'
});
return ckeditorTree;
},
Thanks for the help!
Give this a whirl:
var path = require('path');
var mergeTrees = require('broccoli-merge-trees');
var concat = require('broccoli-concat');
module.exports = {
name: 'myaddon',
treeForVendor: function(tree) {
var trees = [tree];
var ckeditorTree = path.join('bower_components', 'ckeditor_custom');
trees.push(concat(ckeditorTree, {
inputFiles: [
'ckeditor.js',
'styles.js',
'lang/fr.js'
],
outputFile: '/ckeditor.js'
}));
trees.push(concat(ckeditorTree, {
inputFiles: [
'skins/minimalist/editor.css'
],
outputFile: '/ckeditor.css'
}));
return mergeTrees(trees);
},
included: function included(app) {
this.app = app;
app.import('vendor/ckeditor.js');
app.import('vendor/ckeditor.css');
}
};
Ember-cli: 0.33
How can I use web workers within an ember-cli based project?
Example - I have a component and I want to start a web worker:
import Ember from 'ember';
export default Ember.Component.extend({
_startWorker: function() {
var worker = new Worker('path/to/worker.js');
}.on('didInsertElement')
});
In which folder should I put the worker.js file inside the ember-cli project structure?
Which other changes are required (Brocfile.js,...)?
One possible solution:
1) In your ember project root folder add a new folder with the name 'workers'.
2) Update your Brocfile.js (see Screenshot)
3) Write workers :-)
relevant code from #Steven's solution for easy copying:
/* global require, module, process */
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
var pickFiles = require('broccoli-static-compiler');
var app = new EmberApp();
var workers = pickFiles('workers', {
srcDir: '/',
files: ['*.js'],
destDir: '/assets/workers'
});
if (process.env.EMBER_ENV === 'production') {
workers = require('broccoli-uglify-js')(workers, {
mangle: true,
compress: true
});
}
module.exports = app.toTree(workers);
If that helps someone, I managed to start using using workers with the config below, using ember-cli >= 2.4.2 to be able to use outputFile:
//ember-cli-build.js
..
//don't prepend CDN to worker paths (or CORS issue)
fingerprint: {
exclude: ['worker'],
..
}
..
var app = new EmberApp(defaults, {
..
app.import('vendor/localforage.js');//use localforage outside of workers
app.import('vendor/localforage.js',outputFile:'assets/workers/localforage.js'});//use localforage inside of workers
app.import('vendor/worker_localforage.js',outputFile:'assets/workers/worker_localforage.js'});
app.import('vendor/worker_test_indexeddb.js',outputFile:'assets/workers/worker_test_indexeddb.js'});
});
Then the workers code:
//vendor/worker_localforage.js
importScripts('localforage.js');
self.onmessage = function(e) {
var namespace=e.data.namespace;
var msg=e.data.msg;
var data=e.data.data;
//console.log("msg to worker",namespace,msg);
if (msg==="load") {
localforage.getItem(namespace).then(function(res){
self.postMessage({msg:"load",data:res});
});
}
else if (msg==="persist") {
localforage.setItem(namespace,data).then(function(res){
self.postMessage({msg:"persist",data:res});
});
}
};
Calling the workers from anywhere in your app:
self.worker=new Worker("assets/workers/worker_localforage.js");
var worker=self.worker;
prom2= new Ember.RSVP.Promise(function(resolve,reject){
worker.onmessage=function(e){
if (e.data.msg==="load") {
resolve(e.data.data);
}
}
});
worker.postMessage({namespace:self.adapterNamespace(),msg:"load"});