A sophisticated build management system for web apps (formerly ng-boilerplate). Created by @joshdmiller
An opinionated kickstarter for AngularJS projects.
Install Node.js and then:
$ git clone git://github.com/joshdmiller/ng-boilerplate $ cd ng-boilerplate $ sudo npm -g install grunt-cli karma bower $ npm install $ bower install $ grunt watch
file:///path/to/ng-boilerplate/build/index.htmlin your browser.
ngBoilerplateis designed to make life easy by providing a basic framework with which to kickstart AngularJS projects. It contains a best-practice directory structure to ensure code reusability and maximum scalability. ngBoilerplate also comes prepackaged with the most popular design frameworks around: Twitter Bootstrap, Angular UI, Angular Bootstrap, Font Awesome, and LESS. Lastly, it contains a sophisticated Grunt-based build system to ensure maximum productivity. All you have to do is clone it and start coding!
The principal goal of
ngBoilerplateis to set projects up for long-term success. So
ngBoilerplatetries to follow best practices everywhere it can. These are:
testdirectory required; the build process should be sophisticated enough to handle this.
ngBoilerplateis not an example of an AngularJS app: this is a kickstarter. If you're looking for an example of what a complete, non-trivial AngularJS app that does something real looks like, complete with a REST backend and authentication and authorization, then take a look at
angular-app, which does just that - and does it well.
At a high level, the structure looks roughly like this:
ng-boilerplate/ |- grunt-tasks/ |- karma/ |- src/ | |- app/ | | |- | |- assets/ | | |- | |- common/ | | |- | |- less/ | | |- main.less |- vendor/ | |- angular-bootstrap/ | |- bootstrap/ | |- placeholders/ |- .bowerrc |- bower.json |- build.config.js |- Gruntfile.js |- module.prefix |- module.suffix |- package.json
What follows is a brief description of each entry, but most directories contain their own
README.mdfile with additional documentation, so browse around to learn more.
karma/- test configuration.
src/- our application sources. Read more »
vendor/- third-party libraries. Bower will install packages here. Anything added to this directory will need to be manually added to
karma/karma-unit.jsto be picked up by the build system.
.bowerrc- the Bower configuration file. This tells Bower to install components into the
bower.json- this is our project configuration for Bower and it contains the list of Bower dependencies we need.
build.config.js- our customizable build settings; see "The Build System" below.
Gruntfile.js- our build script; see "The Build System" below.
module.suffix- our compiled application script is wrapped in these, which by default are used to place the application inside a self-executing anonymous function to ensure no clashes with other libraries.
package.json- metadata about the app, used by NPM and our build script. Our NPM dependencies are listed here.
This section provides a little more detailed understanding of what goes into getting
ngBoilerplateup and running. Though
Okay, ready to go? Here it is:
ngBoilerplateuses Grunt as its build system, so Node.js is required. Also, Grunt by default no longer comes with a command-line utility and Karma and Bower must end up in your global path for the build system to find it, so they must be installed independently. Once you have Node.js installed, you can simply use
npmto make it all happen:
$ npm -g install grunt-cli karma bower
If you're on Linux (like I am) then throw
sudoin front of that command. If you're on Windows, then you're on your own.
Next, you can either clone this repository using Git, download it as a zip file from GitHub, or merge the branch into your existing repository. Assuming you're starting from scratch, simply clone this repository using git:
$ git clone git://github.com/joshdmiller/ng-boilerplate my-project-name $ cd my-project-name
And then install the remaining build dependencies locally:
$ npm install
This will read the
dependencies(empty by default) and the
devDependencies(which contains our build requirements) from
package.jsonand install everything needed into a folder called
There are many Bower packages used by
ngBoilerplate, like Twitter Bootstrap and Angular UI, which are listed in
bower.js. To install them into the
vendor/directory, simply run:
$ bower install
In the future, should you want to add a new Bower package to your app, run the
$ bower install packagename --save-dev
--save-devflag tells Bower to add the package at its current version to our project's
bower.jsfile so should another developer download our application (or we download it from a different computer), we can simply run the
bower installcommand as above and all our dependencies will be installed for us. Neat!
ngBoilerplateis now ready to go.
However, prior to hacking on your application, you will want to modify the
package.jsonfile to contain your project's information. Do not remove any items from the
devDependenciesarray as all are needed for the build process to work.
To ensure your setup works, launch grunt:
$ grunt watch
The built files are placed in the
build/directory by default. Open the
build/index.htmlfile in your browser and check it out! Because everything is compiled, no XHR requests are needed to retrieve templates, so until this needs to communicate with your backend there is no need to run it from a web server.
watchis actually an alias of the
grunt-contrib-watchthat will first run a partial build before watching for file changes. With this setup, any file that changes will trigger only those build tasks necessary to bring the app up to date. For example, when a template file changes, the templates are recompiled and concatenated, but when a test/spec file changes, only the tests are run. This allows the watch command to complete in a fraction of the time it would ordinarily take.
In addition, if you're running a Live Reload plugin in your browser (see below), you won't even have to refresh to see the changes! When the
watchtask detects a file change, it will reload the page for you. Sweet.
When you're ready to push your app into production, just run the
$ grunt compile
This will concatenate and minify your sources and place them by default into the
bin/directory. There will only be three files:
your-app-name.css. All of the vendor dependencies like Bootstrap styles and AngularJS itself have been added to them for super-easy deploying. If you use any assets (
src/assets/) then they will be copied to
Lastly, a complete build is always available by simply running the default task, which runs
The best way to learn about the build system is by familiarizing yourself with Grunt and then reading through the heavily documented build script,
Gruntfile.js. But you don't need to do that to be very productive with
ngBoilerplate. What follows in this section is a quick introduction to the tasks provided and should be plenty to get you started.
The driver of the process is the
deltamulti-task, which watches for file changes using
grunt-contrib-watchand executes one of nine tasks when a file changes:
Gruntfile.jschanges, this task runs the linter (
jshint) on that one file and reloads the configuration.
delta:assets- When any file within
src/assets/changes, all asset files are copied to
src/index.htmlchanges, it is compiled as a Grunt template, so script names, etc., are dynamically replaced with the correct values configured dynamically by Grunt.
delta:less- When any
src/less/main.lessfile is linted and copied into
src/that does not end in
delta:coffeesrc- When any
src/that doesn't match
*.spec.coffeechanges, the Coffee scripts are compiled independently into
build/srcin a structure mirroring where they were in
src/so it's easy to locate problems. For example, the file
src/common/titleService/titleService.coffeeis compiled to
delta:tpls- When any
src/common/and another for
src/app/) that will add the template to AngularJS's
delta:jsunit- When any
src/changes, the test files are linted and the unit tests are executed.
delta:coffeeunit- When any
src/changes, the test files are linted, compiled their tests executed.
As covered in the previous section,
grunt watchwill execute a full build up-front and then run any of the aforementioned
delta:*tasks as needed to ensure the fastest possible build. So whenever you're working on your project, start with:
$ grunt watch
And everything will be done automatically!
To make the build even faster, tasks are placed into two categories: build and compile. The build tasks (like those we've been discussing) are the minimal tasks required to run your app during development.
Compile tasks, however, get your app ready for production. The compile tasks include concatenation, minification, compression, etc. These tasks take a little bit longer to run and are not at all necessary for development so are not called automatically during build or watch.
To initiate a full compile, you simply run the default task:
This will perform a build and then a compile. The compiled site - ready for uploading to the server! - is located in
bin/, taking a cue from traditional software development. To test that your full site works as expected, open the
bin/index.htmlfile in your browser. Voila!
ngBoilerplatealso includes Live Reload, so you no longer have to refresh your page after making changes! You need a Live Reload browser plugin for this:
Note that if you're using the Chrome version with
file://URLs (as is the default with
ngBoilerplate) you need to tell Live Reload to allow it. Go to
Menu -> Tools -> Extensionsand check the "Allow access to file URLs" box next to the Live Reload plugin.
When you load your page, click the Live Reload icon in your toolbar and everything should work magically. w00t!
If you'd prefer to not install a browser extension, then you must add the following to the end of the
This is a project that is not broad in scope, so there's not really much of a wish list here. But I would like to see a couple of things:
I'd like it to be a little simpler. I want this to be a universal starting point. If someone is starting a new AngularJS project, she should be able to clone, merge, or download its source and immediately start doing what she needs without renaming a bunch of files and methods or deleting spare parts. What I have works for a first release, but I just think there is a little too much here right now.
I'd also like to see a simple generator. Nothing like Yeoman, as there already is one of those, but just something that allows the user to say "I want Bootstrap but not Font Awesome and my app is called 'coolApp'. Gimme." Perhaps a custom download builder like UI Bootstrap has. Like that. Then again, perhaps some Yeoman generators wouldn't be out of line. I don't know. What do you think?
Naturally, I am open to all manner of ideas and suggestions. See the "Contributing" section below.
See the issues list. And feel free to submit your own!
This is an opinionated kickstarter, but the opinions are fluid and evidence-based. Don't like the way I did something? Think you know of a better way? Have an idea to make this more useful? Let me know! You can contact me through all the usual channels or you can open an issue on the GitHub page. If you're feeling ambitious, you can even submit a pull request - how thoughtful of you!
Make sure to check out the Contributing Guide.
So join the team! We're good people.