Ember-cli is the new hotness in the Ember world for generating new applications. The build process for ember-cli is provided by broccoli, a relatively new build tool. Trying to get a Sass version of Twitter bootstrap to play nicely with ember-cli turned out to be a bit of a challenge. Both ember-cli and broccoli are under heavy development, so I imagine that the process for using something like bootstrap-sass will become much easier in the very near future. The solution presented here is a quick and easy way to get things working today, but hopefully there will be an easier and more elegant long-term solution.
This article was written for ember-cli
version 0.0.25. Version 0.0.27 is out now and things have gotten much easier. Please see this post about how to do this in ember-cli 0.0.27
For purposes of demonstration let's start with a clean new app. (You can find a complete repo of this example here.)
$ ember new ember-cli-bootstrap-sass
Easy peasy!
Out of the box ember-cli/broccoli doesn't come with the ability to deal with Sass files. So we need to install a broccoli extension.
$ npm install --save-dev broccoli-sass
At this point we can move app/styles/app.css
to app/styles/app.scss
and the build process will automatically detect that it should be
compiled with the broccoli-sass extension.
You can see that this is working by moving the file and updating it to look like this:
html, body {
margin: 20px;
h2{
text-decoration:underline;
}
}
Then you should see something like this:
Now we need to find a sass version of bootstrap and get it into the project somehow. After a quick search on bower.io it looks like boostrap-sass-official is the way to go. So we can install that into the project by running this command:
$ bower install --save bootstrap-sass-official
At this point, you can include bootstrap at the top of app.scss
to get bootstrap included.
@import 'bootstrap';
html, body{
...
}
The bad news is that now you'll see a build error.
It's a big hairy error message, but the important part says this:
file to import not found or unreadable: "bootstrap/variables"
The issue is that bootstrap doesn't come as one giant scss file,
rather there is the main bootstrap.scss
file, and then it includes dozens of additional scss files. Broccoli is able to find the main file, but it doesn't locate the additional files that bootstrap needs.
At this time there isn't a way to tell the ember-cli build process where to look for additional files. (Maybe there is a way, and I just couldn't locate any information about it?) So, what we need to do is to stop the built in process from trying to compile the sass since it doesn't know where to find the bootstrap partials. Then we'll implement our own pipeline to compile the sass with all of the partials.
Ember-cli watches for files with the .scss
extension and autmatically passes them through a sass compiler. I haven't found a way to prevent that from happeneing, so my solution was to rename app.scss
to app.custom_scss
. You can use whatever other extension you want, it just can't be .scss
or .sass
. (This is one of the ugliest parts since it will likely doink with syntax highlighting.)
$ mv app/styles/app.scss app/styles/app.custom_scss
More bad news is that ember-cli expects app/styles/app.css
or app/styles/app.scss
to be in place, so we need to leave an empty file there for it to find.
$ echo "/* See app.custom_scss */" > app/styles/app.scss
At this point you should have a passing build, but since we haven't setup compilation for app.custom_scss
yet you won't have any styles.
app.custom_scss
Now we can update Brocfile.js
to add our own custom sass compilation step.
First you should remove the last line of the default Brocfile
.
// Remove this line
module.exports = app.toTree();
Then replace it with these lines:
// Import a couple of modules;
var compileSass = require('broccoli-sass');
var mergeTrees = require('broccoli-merge-trees');
// List all of the directories containing SASS source files
var sassSources = [
'app/styles',
'vendor/bootstrap-sass-official/vendor/assets/stylesheets'
]
// Compile a custom sass file, with the sources that need to be included
var appCss = compileSass( sassSources , 'app.custom_scss', 'assets/app.css');
// Merge the ember app and the custom css into a single tree for export
var appAndCustomDependencies = mergeTrees([app.toTree(),appCss], {
overwrite: true
});
// EXPORT ALL THE THINGS!
module.exports = appAndCustomDependencies;
We also need to install one more broccoli extension to make this work.
$ npm install --save-dev broccoli-merge-trees
Now when you run ember build
you should have a file in dist/assets/app.css
that contains your own styles and all of the bootstrap sass compiled down to css.
You can see that the sass mixins are available by updating app/styles/app.custom_scss
to look like this:
@import 'bootstrap';
h2{
@extend .text-primary;
}
Now your running app should look something like this:
Well, it's not all that pretty, but it works. I've put together a demo repo and I'd love to hear comments and criticisms on this approach. Please tweet at me or send me an email if you have any feedback. Now I'm off to read some ember-cli
source code to try to figure out how to make this a smoother process. Maybe I'll have a PR for something soon…
Just in case you missed the update at the beginning, this article was written for ember-cli
version 0.0.25. Version 0.0.27 is out now and things have gotten much easier. Please see this post about how to do this in ember-cli 0.0.27