Building Web Apps Faster Using Angus
Nick's outstanding utility, Angus, has changed! Click here to read an updated post!
When it comes to building web apps, there are a couple of tools available that help you develop faster. There's GruntJS, GulpJS, Brunch and others which streamline your workflow by doing a series of build tasks:
- Test the code
- Clean the build directory
- Copy source files to the build folder
- Do some magic tricks on your copied files, such as replacing variable names.
- Compile Less or Sass files
- Dynamically generate script tags for your index.html
- Run a webserver to test out your app locally
- Watch for code changes and re-build
- ...
These tools do an outstanding job of helping you develop your web app faster. Huzzah!
Let's Build Another App!
Once you have finished your app and have started on a new project, you again would like to have a good build configuration. You have optimised your last app's build config so it builds as efficiently as possible, and it's got some cool gimmicks like that AWS S3 deploy task which you spent a couple of hours on last weekend.
Obviously, you want to reap the fruits of your hard labor and use those new and optimised build tasks in your new app as well. What to do now? There are a couple of ways.
Duplicating the Old App
You could just copy paste your old app folder, rename it and start working. The problem comes when you are improving your build setup even further. By now, there are likely newer and faster build tasks available, so you eagerly start implementing those in your new app. And wow, now there's a soft CSS refresh feature in the new app!
A few days later you need to bring an update to your old app. You painfully notice some cool features are missing in the old app's build config. Like that soft CSS refresh and the numerous performance updates you've made. What now?
Yeoman
One solution to the problem is Yeoman, a scaffolding tool. It generates your build config by asking questions, every time you make a new app. On its website you can find plenty of generators which include web frameworks and build tasks that have been set-up for you. These generators are maintained by many people and you will reap the benefits of their optimisations when you generate a new app.
Generators aren't perfect however. When they are updated to include new tools and optimisations, you are stuck with your old build config. You can't simply update without generating and answering those scaffolding questions again. In addition, it is likely that your ideal build config requires changing or adding tasks such as the AWS S3 deploy which you need for your particular client.
The problem is that at the end of the day, you are again duplicating logic. When you have several apps, it is very likely that the build steps are similar if not identical. If you want to change something there or add a cool new build feature to many apps, you're out of luck.
Don't Repeat Yourself
A build config is just like any other code. You should not repeat yourself and you want to re-use your build config across different apps. What if there was a way to use one build configuration for all your apps?
Introducing Angus
Amid growing frustration with the state of things, I decided to make a generic and pre-configured build framework called Angus.
Angus is a pre-configured build framework that you simply clone as a git repository. Inside this repo, you build your apps inside an apps/
folder which gets ignored by the Angus repo. For each app, you can define which libraries and build steps you would like to use. Every build task is already configured to work with other tasks.
The framework uses GruntJS to do all build steps. The cool thing is that you don't need to configure anything, you just need to tell which tasks you'd like to enable per app.
Project Structure
angus/ <-- angus repository Gruntfile.js grunt/ <-- generic build tasks apps/ hello-world/ my-second-app/ <-- app sub repository assets/ scss/ app.js config.js index.html
Apps Inside!
Unknown to many, Git repositories can actually exist within each other without using rocket science like submodules. Inside Angus, the apps/
folder gets ignored by git. You can safely create sub-folders inside apps/
which have their own repositories! To do so, simply create a folder inside the apps/
folder and run git init
.
Given this structure, you can develop as many apps as you like without having to generate or adjust build configurations.
Configuring Each App
Every app inside Angus has its own configuration file, config.js
. In this file, you can define Bower libraries and tell Angus which files from Bower you actually need. When including Bootstrap for instance, you may only really need a couple of .scss
files.
**Example config file** packages: [ 'angular', 'bootstrap-sass-official' ], // A list of files which this app will actually use from the bower packages above. // Angus will look inside bower_components/ for these files. libIncludes: { js: [ 'angular/angular.js' ], scss: [ // Core variables and mixins 'bootstrap-sass-official/assets/stylesheets/bootstrap/_variables.scss', 'bootstrap-sass-official/assets/stylesheets/bootstrap/_mixins.scss', 'bootstrap-sass-official/assets/stylesheets/bootstrap/_grid.scss' ] }
Running the App
Simply run grunt dev
, and Angus takes care of the rest. By default it will launch the hello-world
application, but you can pass the —app=your-app
parameter or change the config.json
file in the root Angus folder.
Angus will automatically install Bower packages, auto include libraries and serve your app. It comes with [pushState support](http://diveintohtml5.info/history.html), auto-refresh on code changes and soft CSS refresh on CSS changes.
Deploying
Angus also includes a grunt prod
command, which takes care of minification, uglifying and concatenating. The output of your files will be inside the dist/prod/
folder. You can even deploy directly to Amazon S3 with one command.
Additional Tasks
You can easily enable additional tasks you would like your app to execute. If you're running AngularJS, chances are you'll be wanting to use common build tasks specific to AngularJS such as template minifying, constants generation and the ng-min library.
The cool thing is, these tasks are already preconfigured! You just need to enable them as follows in your config.js
file:
// In addition to the default task list (core/defaultTasks.js), also execute these gruntTasksAdd: [ 'html2js', 'ngconstant', 'ngmin', 'karma' ],
The Future
Angus is still a very fresh project, and I encourage you to help out by checking out the source code and sending pull requests. In the future, we may even switch to newer tools such as GulpJS or Brunch, but with the same philosophy. Don't repeat yourself!
I hope I have given you fresh insights into the build process of web apps, and how Angus can increase your productivity. Give it a try and let me know what you think!
About Nick Janssen
Nick Janssen is a full-stack web developer with a passion for creating cool applications, originally from Belgium.
It’s actually not the case that you must “answer” generator questions again, while using Yeoman. Having built a number of generators myself, I know that any good generator will store configuration details in the package.json file.
Nice concept, will check it out. I’m using more and more Node tools lately and was trying to think of a clean way to speed this process up :)
Excellent concept and great tutorial. I will recommend this to friends in the future.
Say yeah for Angus. It can’t be more easier for me to DRY config files.
This article needs to be updated, the example is based on grunt, he did the switch to gulp.
Nice system anyway! We did something similar with grunt/gulp and process-html and a lot of for-each loops. It doesnt work well with many Apps in the app Folder. We got also some global folders for global scss, like the bower part, but managed by our own.