Modular AngularJS and Ionic architecture: a first step towards AngularJS 2

This post describes the architecture that you can use RIGHT NOW on your AngularJS 1.x or Ionic applications and that will be compatible with AngularJS 2. When the time comes and according to this article: Angular 1 and 2 running together, you will be able to migrate easily your application, module by module.

Forget what you know

A large majority of the Ionic, AngularJS 1.x projects are using Bower, Gulp and a folder-by-type architecture. If you want to build large scale applications with several developers, you will definitely have problems if you follow that kind of architecture.

AngularJS is often used to create prototypes and MVP really quickly so why bother? Well, we all know what happen to prototypes and MVPs that somehow work… they go directly into production. If you have reached that point, it is not too late to restructure your code and think about it before your application turns into FrankenstApp!


Bower

Here are few reasons not to use Bower:

  1. It does not support CommonJS out of the box.
  2. Using npm and Bower at the same time is a non sense (they both fulfill the same need).
  3. npm has become the most popular package manager for JavaScript.
  4. Requires closures to avoid scope leaking.

If you want to know more reasons I recommend you to read this article: Why my team uses npm instead of bower

What is CommonJS?

The CommonJS group defined a module format to solve JavaScript scope issues by making sure each module is executed in its own namespace.

CommonJS handle modules outside the browser and works great with ECMAScript 5 or 6.

// Import with ECMAScript 5
var angular = require('angular');

// Export with ECMAScript 5
module.exports = function(){}

// Import with ECMAScript 6
import angular from 'angular';

// Export with ECMAScript 6
export default function(){}

Gulp

Few reasons not to use Gulp:

  1. Compiling, concatenating and minifying your application require to install a lot of dependencies (gulp-concat, gulp-minify-css, express, livereload etc.).
  2. Basic needs (web server, livereload, concat etc) require to create many scripts that YOU will need to maintain yourself.

In 2015 it should not be that complicated to fulfill your application’s basic needs. The solution is to use Webpack.


Folder-by-type structure

The folder-by-type structure is basically grouping JavaScript files by types (controllers, configs, views, directives etc.) as followed:

app/
    app.js
    controllers/
        aaa.js
        bbb.js
        ccc.js
    directives/
        ddd.directive.js
        eee.directive.js
        fff.directive.js
    services/
        xxx.js
        yyy.js
        zzz.js
    views/
        aaa.html
        bbb.html
        ccc.html
        ddd.directive.html
        eee.directive.html
        fff.directive.html

This folder architecture is a terrible idea for large scale applications. I have experienced it before and it is not a good memory, especially if you are several developers to work at the same time. Here are some reasons not to use it:

  1. The number of files in your folders can become really large.
  2. Finding all the files you need to modify for a specific feature can be tricky.
  3. Working on a feature will lead to open many folders.

If you do not trust me, at least trust John Papa’s styleguide 🙂

A better solution is to Create components/modules with a Folders-by-Feature structure.


Use Webpack

Webpack is a module bundler, it takes modules with dependencies and generates static assets.

Webpack and Webpack-dev-server easily replace Gulp for basic application needs (web server, livereload, concatenation, minification, compliling JS or Sass etc.). Instead of having to maintain several Gulp scripts, what you only need is a configuration file webpack.config.js… that’s ALL!

For instance having an autoprefixed CSS injected into your application from several Sass files is as simple as that with Webpack:

{
    test: /.scss$/,
    loader: "style!css!autoprefixer!sass"
}

No need to show you the equivalent using Gulp or Grunt, I think you got my point! If you want to go further with Webpack you can read this article I created some time ago: Introduction to Webpack with practical examples


Create components/modules

The solution to large scale applications is to create loosely coupled modules. I have been doing AngularJS applications for a long time now and after a lot of experimenting I have settled to the following architecture:

  • Every file that can be edited, live in the src/ or /lib folder.
  • Every AngularJS module needs a proper folder.
  • Every module file *.module.js must define a unique namespace (and must be the only place where this namespace appears).
  • Every module file *.module.js must declare all its dependencies (even if dependencies are already injected in the app).
  • Every module file *.module.js must declare all its configs, controllers, services, filters etc.
  • Every config, controller, service, filter etc. must export a function or a Class.
  • If a module needs some specific style, the .scss file must live within the module as well.

All of this is very powerful, it assures you to have modules that can be shared by several applications without getting any error (except for missing dependencies).

Here an example of a home module structure:

lib/
    index.js
    home/
        home.module.js
        home.config.js
        home.service.js
        home.controller.js
        home.html
        home.scss

Now here is the home.module.js file using ECMAScript 6:

import modConfig from './home.config';
import modController from './home.controller';

let mod = angular.module('prototype.home', [
    'ionic',
    'ui.router'
]);

mod.config(modConfig);
mod.controller('HomeController', modController);

export default mod = mod.name

Use Folders-by-Feature structure

Reasons to use Folders-by-Feature structure:

  1. The number of files in your folders are limited to few.
  2. Finding all the files you need to modify for a specific feature is easy (they are in the same folder!).
  3. You can work independently on a feature.
  4. Knowing what the module represents is easy (the folder name is sufficient).
lib/
    index.js
    home/
        home.module.js
        home.config.js
        home.service.js
        home.controller.js
        home.html
        home.scss
    parameters/
        parameters.module.js
        parameters.config.js
        parameters.service.js
        parameters.controller.js
        parameters.html
        parameters.scss

Recommended boilerplates

If you are ready to start making some changes in your application with the architecture I suggested in this post you can clone those repositories, they are a good start:

  1. [Angular Material]: shprink/angular1.4-ES6-material-webpack-boilerplate. A simple AngularJS 1.4 boilerplate using ES6, material design and Webpack.
  2. [Ionic]: shprink/ios-android-wordpress-ionic-webpack-ES6. Repo created for the TutsPlus article: Creating iOS/Android mobile applications for WordPress using Ionic SDK, Webpack, ES6 and WP-API.

One thought on “Modular AngularJS and Ionic architecture: a first step towards AngularJS 2”

Leave a Reply

Your email address will not be published. Required fields are marked *