Design – AngularJS: structuring a web application with multiple ng-apps

angularjsdesignweb-applications

The blogosphere has a number of articles on the topic of AngularJS app structuring guidelines such as these (and others):

However, one scenario I have yet to come across for guidelines and best practices is the case where you have a large web application containing multiple "mini-spa" apps, and the mini-spa apps all share a certain amount of code.

I am not referring to the case of trying to have multiple ng-app declarations on the same page; rather, I mean different sections of a large site that have their own, unique ng-app declaration.

As Scott Allen writes in his OdeToCode blog:

One scenario I haven't found addressed very well is the scenario where
multiple apps exist in the same greater web application and require
some shared code on the client.

Are there any recommended approaches to take, pitfalls to avoid, or good sample structures of this scenario that you can point to?


Update – 9/10/2015
One project with an interesting organization strategy is MEAN.JS and its modules folder.
https://github.com/meanjs/mean
https://github.com/meanjs/mean/tree/master/modules

Another example is from the ASP.NET Music Store SPA example.
https://github.com/aspnet/MusicStore
https://github.com/aspnet/MusicStore/tree/master/src/MusicStore.Spa/ng-apps

Best Answer

Here is the design that I work with. I found it useful on two larger projects I built and haven't hit any road blocks so far.

Folder Structure

your-project/
  apps/
    global.html
    app1/
      index.html
      app1.module.js
      app1.js
      parts/
        foo.js
        foo.html
        ...
    app2/
  libs
    lib1/
      lib1.module.js
      parts/
        directive1.js
        directive1.html
    lib2/
  third-party/
  • Configure your server web framework to find apps/app1/index.html when a request for /app1 comes in. Use friendly URLs (e.g. the-first-application/ instead of app1/ and map them using your server technology if required.
  • Your server technology must include global.html in index.html because it contains the vendor includes (see below).
  • Include the assets required by the respective app in index.html (see below).
  • Put the ng-app and the root <div ui-view></div> in the index.html.
  • Every app and lib is a separate angular module.
  • Every app gets a <app-name>.module.js file that contains the angular module definition and dependency list.
  • Every app gets a <app-name>.js file that contains the modules' config and run blocks, and the routing config as part of it.
  • Every app gets a parts folder that contains the applications' controllers, views, services and directives in a structure that makes sense for the specific app. I don't consider sub-folders like controllers/, views/ etc helpful, because they don't scale, but YMMV.
  • Libs follow the same structure as apps, but leave things out that they don't need (obviously).

Start out with services and directives within the app where they are used. As soon as you need something in another app as well, refactor to a library. Try to create functionally consistent libraries, not just all-directive or all-services libraries.

Assets

I minify both JS and CSS files for release builds but work with unminified files during development. Here's a setup that support this:

  • Manage vendor includes globally in global.html. This way, the heavy stuff can be loaded from cache when navigating between SPAs. Make sure caching works appropriately.
  • Per-SPA assets are defined in index.html. This should only include the app-specific files as well as the used libraries.

The folder structure above makes it easy to find the right files for the minification build steps.

Related Topic