Using SASS, ES6 Javascript, and Node modules with Brunch
Aug 31 2015
Brunch has recently become my favourite front end build tool, to the point where I don’t want to use Grunt or the Rails Asset Pipeline ever again. Why is this? Two reasons…
It’s fast Really fast. It doesn’t use any temporary intermediary files, it’s builds are incremental, and it makes clever use of caching to avoid doing work that it doesn’t have to. As a result it’s much faster than Grunt and Gulp.
It’s simple. Remember those horrible several hundred line Grunt configs
manipulating a tmp/
directory? Or those Gulp configs full of pipeline logic?
Well a Brunch config that does the same probably looks something like this:
exports.config = {
files: {
javascripts: { joinTo: 'main.js' },
templates: { joinTo: 'main.js' },
stylesheets: { joinTo: 'main.css' },
},
};
Yes, really.
This is because it’s a specialised build tool, not a task runner like Grunt or Rake. It has one specific set of tasks, and it can use conventions to make this cleaner and easier.
Additionally, if I want to use a plugin that adds additional functionality
(for example, CSS minification), it’s just a matter of installing the plugin
module with npm
, and Brunch will pick it up and plug it in for us.
The Brunch problem
It’s not all perfect though. Because all the logic happens behind the scenes, it’s possible to get into a situation where something does not work, and it’s difficult to say what you’ve done wrong. This can become even more frustrating when coupled with the fact that the documentation on the various conventions and plugins often leaves a lot to be desired.
Because of this, I thought I should write a little something about setting
Brunch up to do what I generally want from my front end build tool- ES6
Javascript using the Babel transpiler, SCSS instead of
CSS, jshint linting my Javascript, minification for both CSS and
Javascript, and the ability to import Javascript libraries from npm
.
The conventions
By convention Brunch will look for source files in app/
, and output
generated files to public/
, so put your Javascript files in app/
. A small
project of mine look something like this:
app/
├── assets
│ └── index.html
├── controllers
│ └── users.js
├── main.js
├── models
│ └── user.js
├── stylesheets
│ ├── components
│ │ ├── _button.scss
│ │ └── _search.scss
│ ├── layouts
│ │ ├── _footer.scss
│ │ └── _header.scss
│ └── main.scss
└── views
└── users.jade
And after Brunch has done its thing the output directory looks like this:
public/
├── index.html
├── main.css
└── main.js
Things to note:
- Files in the
app/assets/
directory are copied directly into thepublic/
directory. - All our Javascript has been compiled into one file, one that we have specified the name and location of.
- All of our SCSS has been compiled into one file, one we have also specified the name and location of.
- Our SCSS, Javascript, and template files (
.jade
in this case) all live withinapp/
.
ES6 setup
First, lets get ES6 Javascript compilation working, complete with ES6 modules, etc.
Install brunch
, the mandatory javascript-brunch
plugin that handles
Javascript compilation, and the babel-brunch
plugin, which gives us ES6
Javascript support. We’ll want brunch
installed globally so we’ll have the
brunch
command in our $PATH
.
npm install -g brunch
npm install --save brunch javascript-brunch babel-brunch
Great! Now let’s make our Brunch config file, brunch-config.js
// brunch-config.js
exports.config = {
files: {
javascripts: { joinTo: 'main.js' },
templates: { joinTo: 'main.js' },
},
};
We’re not actually setting up any template systems, such as the excellent
jade-brunch, so we could drop the templates
line, but
there’s no harm in keeping it in the config.
And that’s it. Run brunch watch
to start Brunch, and create some test ES6
Javascript files.
// app/main.js
import test from 'test';
test();
// app/test.js
export default function test() {
console.log('Hello, world!');
}
Boom. We have a generated file at public/main.js
that’s ready to be loaded
into the browser. Once you’ve done that, exec require('main');
, and your
Javascript application will run.
That’s it. We’ve set up ES6 Javascript with Brunch.
SCSS setup
Onto the equally difficult process of adding SCSS compilation.
npm install --save css-brunch sass-brunch
Add a stylesheets line to your brunch config:
// brunch-config.js
exports.config = {
files: {
javascripts: { joinTo: 'main.js' },
templates: { joinTo: 'main.js' },
stylesheets: { joinTo: 'main.css' },
},
};
And then create some SCSS files under app/
, and use the usual SCSS import
statements. I like to keep them in app/stylesheets/
.
Done that? Then you should have a compiled CSS file at public/main.css
.
Super easy.
Using libraries from npm
There’s lots of handy libraries on npm that we might want to use in our Javascript app. lodash, for example. Install it, as per usual:
npm install --save lodash
Enable npm support in your Brunch config:
// brunch-config.js
exports.config = {
files: {
javascripts: { joinTo: 'main.js' },
templates: { joinTo: 'main.js' },
stylesheets: { joinTo: 'main.css' },
npm: { enabled: true },
},
};
And then import it in your Javascript like a regular module.
// app/main.js
import _ from 'lodash';
import test from 'test';
test();
Boom. It works.
Javascript linting with jshint
Add your config as a .jshintrc
file in the project directory, and then
install the plugin.
npm install --save jshint-brunch
Minification
Lastly, CSS and Javascript minification.
npm install --save uglify-js-brunch clean-css-brunch
Run brunch build --production
to see it in action.
So that’s it. We’ve set up everything with Brunch. Told you it was easy. :)