Using AngularJS with RequireJS, Grunt and JohnPapa’s Angular Style Guide
Angularjs users would be familiar with the Angular Style Guide by John Papa. The guide has been very well received (16k stars and 2k forks as of 2016-03-01) and lays down all the common patterns and mistakes one can make while using AngularJS. While working on https://app.statusbrew.com, which uses Angularjs and Angular-Material, we made sure that we strictly follow the above style guide. But we also had some future development of others apps in mind, not just for https://app.statusbrew.com, but using parts of those code to make a Chrome Extension, Chrome App and more. We needed a way to further modularize our code base so that we can pick up bits and pieces of the same code to spin off new projects.
We needed a way to ensure that we do not explode the code with other unnecessary libraries (as Angular and Angular Material are already huge code bases in themselves). I was already familiar with RequireJS, but we also needed to make sure that while we follow the Style Guide, we also are able to do automation with grunt for creating all our assets, while making it easier to do the development using watch, etc.
I have created a sample repo to share how we have done it in app.statusbrew.com. The main components of the sample are:
Keeping index.html as clean as possible with only one entry source to all the javascript files
Making the app as modular as possible at various levels. ex. Ex.App, Ex.WebApp, Ex.Common, Ex.Common.Filters etc. This makes it easy to pick and chose any module as needed
[TODO] Making it easier to create various distributions. ex. webapp, chromapp etc
The File structure with the basic description of the components are as follows:
. ├── Gruntfile.js ├── app │ ├── app.js <-- entry point for require.js │ ├── index.html │ ├── modules <-- this is where all your top level modules/apps are │ │ ├── common <-- services/providers/models/configs commmon to all other modules │ │ │ ├── common.module.js <-- angular.module('Ex.Common') │ │ │ ├── config │ │ │ │ ├── config.module.js <-- angular.module('Ex.Common.Config') │ │ │ │ ├── c1.config.js <<- some config │ │ │ │ └── c2.config.js <<- another config │ │ │ ├── directives │ │ │ │ ├── directives.module.js <-- angular.module('Ex.Common.Directives') │ │ │ │ └── d1.directive.js <<- some directive │ │ │ ├── filters │ │ │ │ ├── filters.module.js <-- angular.module('Ex.Common.Filters') │ │ │ │ └── f1.filter.js <<- some filter │ │ │ └── utils │ │ │ ├── utils.module.js <-- angular.module('Ex.Common.Utils') │ │ │ └── utils.factory.js │ │ └── app1 │ │ ├── common │ │ │ ├── common.module.js <-- angular.module('Ex.App1.Common') │ │ │ ├── services │ │ │ │ ├── services.module.js <-- angular.module('Ex.App1.Common.Services') │ │ │ │ └── s1.service.js <<- some factory | │ │ └── directives │ │ │ ├── directives.module.js <-- angular.module('Ex.App1.Common.Directives') │ │ │ └── d2.directive.js <<- some directive │ │ ├── state1 │ │ │ ├── state1.controller.js │ │ │ ├── state1.tpl.html │ │ │ ├── child1 │ │ │ │ ├── state1.child1.controller.js │ │ │ │ └── state1.child1.tpl.html │ │ │ └── child2 │ │ │ ├── state1.child2.controller.js │ │ │ └── state1.child2.tpl.html │ │ ├── app1.module.js <-- angular.module('Ex.App1') │ │ └── app1.states.js <-- angular.module('Ex.App1.States') │ └── app1.js ├── bower.json └── package.json
The sample code is available at https://github.com/rishabhmhjn/angularjs-requirejs-style-guide. It’s still very much a work in progress.
Let me know what you think about this in the comments or by creating an issue here