Declarative Build Configurations
Some time ago I posted an article how you can build apps faster using a build tool called Angus. In the meantime the tool has gotten a whole lot better, embracing the concept of declarative build configurations. In this article I would like to show you what that means and how Angus can help you build web apps in a much faster way.
In The Restaurant
Imagine for a second you're sitting in a restaurant. You take a look at the menu. You decide that you would like a Pizza Vegeta today, because you're feeling healthy. Hmm!
Next, you stand up from your table. You walk to the kitchen. You start to delegate.
"You there! Take some dough and make it flat and round."
"And you! Chop some onions, tomatoes and bell peppers."
"Now you, grab the tomato sauce and cheese and put them on the dough."
"Put all those vegetables on the pizza and then put it in the oven for ten minutes!"
After ten minutes, you come back. You put the pizza on your plate, walk to your table and start eating.
GulpJS: A Case Study
Let's wake up, and take a look at a common build tool configuration from GulpJS.
gulp.task('clean', function(cb) { del(['build'], cb); }); gulp.task('scripts', ['clean'], function() { return gulp.src(paths.scripts) .pipe(sourcemaps.init()) .pipe(coffee()) .pipe(uglify()) .pipe(concat('all.min.js')) .pipe(sourcemaps.write()) .pipe(gulp.dest('build/js')); }); gulp.task('images', ['clean'], function() { return gulp.src(paths.images) .pipe(imagemin({optimizationLevel: 5})) .pipe(gulp.dest('build/img')); }); gulp.task('watch', function() { gulp.watch(paths.scripts, ['scripts']); gulp.watch(paths.images, ['images']); }); gulp.task('default', ['watch', 'scripts', 'images']);
If you compare this configuration with the absurd restaurant scene, it's essentially not that different. You're telling Gulp what to do, how to do it and when and where to get your compiled files.
Can we do better than that? What if there was a way to tell Gulp, "Hey, today I'd like a Pizza Vegeta."?
What if there was a tool, where you could say "Today I'd like to have an app that uses AngularJS, some bootstrap, karma as test runner, and hmmmm... I'll have Sass as my CSS compiler this time."
Angus, A Declarative Build Tool
Having built a ton of apps, I've always found myself having to declare the same tasks over and over again, although they essentially stayed the same across my apps. Out of frustration with the state of things, I decided to create a tool called Angus that makes build configurations declarative.
Take a look at a common Angus configuration.
{ bower: { packages: [ 'angular', 'threejs', 'Keypress', 'underscore@1.7.0', 'angular-ui-router', 'hammerjs' ], filesNeeded: { js: [ 'angular/angular.js', 'angular-ui-router/release/angular-ui-router.js', 'Keypress/keypress.js', 'hammerjs/hammer.min.js', 'threejs/build/three.js', 'underscore/underscore.js' ] } }, usesAngularJS: true, testRunner: 'karma', cssCompiler: 'less' };
In essence, I'm telling Angus which bower packages my app needs and which files to actually use from those bower packages. Next I'm declaring it uses AngularJS, Karma as its test runner and Less as its CSS compiler.
That's it. There are no other hidden configuration files. I just run angus dev
from the command line and my app launches in the browser, ready to go.
Angus takes care of everything. It installs your bower packages, minifies your files, compiles your CSS, watches for changes and launches your app in a browser. But there's a lot more features.
Convention Over Configuration
Angus applies the concept of convention over configuration so that it doesn't burden the user with making unnecessary choices such as where to store the distributed files. For one, it requires you to layout your source files in a way that's common for web apps.
hello-world/ bower_components/ src/ assets/ style/ core/ index.html angus.config.js
This makes things a lot simpler. By having your source files structured in the same way for every app, Angus can automatically build your app without you having to specify where your source and library files are.
Next, all underlying tasks use this folder structure to build your app. All common tasks are pre-configured, Angus just tells them whether to execute or not based on your config file. Again, it's declarative.
In addition, it's a lot easier to maintain. For example, if you wanted to switch to another CSS compiler, it's simply a matter of enabling it in your config file.
Quick Start
Getting started with Angus is easy. Just install it with npm install -g angus
.
Next, create a sample app by doing angus create hello-world
. This will create a folder hello-world
.
Inside this folder, run angus dev
and open your browser to visit http://localhost:9000/
.
That's it! For further information, please refer to the detailed readme on GitHub.
Conclusion
I hope that this article has given you new insights in how declarative build configurations can help you focus your efforts on your app and not your build process. Angus has gotten a lot of good feedback so far, and I invite you to try it out and make an opinion for yourself. If you have any questions I will be happy to answer them in the comments section below.
About Nick Janssen
Nick Janssen is a full-stack web developer with a passion for creating cool applications, originally from Belgium.