0

I am developing an Angular SPA and I am currently in the design phase. I have created a sample architecture which I am planing to use in my SPA but I would get some feedback because I want the architecture to be scalable and maintainable. I have tested this architecture out and it works so far.

My Current Architecture:

  1. I have "Main" module where my ngRoute resides and from there I will control my apps routes.
  2. I have created a separate module for each distinct functionality of my app for example (DashboardCtrl, AdminCtrl, blogCtrl etc)
  3. As its an SPA and its better to bootstrap only 1 angular app in the html page I bootstrap (ng-app="mainApp") on the front-end. But I add all other modules within the main module as dependencies.

Important:

As its an SPA I am using resolve property of ngRoute to get the data from the server before loading the view and then passing the resolved data to a specific controller responsible for that functionality.

Main Module:

var app = angular.module('app',['ngRoute','app.blog','routeService']);

app.config(function($routeProvider) {
    $routeProvider

        // route for the home page

        .when('/', {
            templateUrl: '/overview.html',
            controller: 'mainCtrl'
        })

        // route for the about page
        .when('/blog', {
            templateUrl : '/blog.html',
            controller  : 'blogCtrl',
            resolve: {

                myDta: function(dataFetch){
                    return dataFetch.getProposals();
                }}
        })

        // route for the contact page
        .when('/bios', {
            templateUrl : 'bios.html',
            //controller  : 'contactController'
        });


});

 app.run(['$rootScope', function($root) {

 $root.$on('$routeChangeStart', function(e, curr, prev) { 
   if (curr.$$route && curr.$$route.resolve) {
    // Show a loading message until promises are not resolved
    $root.loadingView = true;
   }
 });

 $root.$on('$routeChangeSuccess', function(e, curr, prev) { 
   // Hide loading message
   $root.loadingView = false;
 });

 }]);


   app.controller('mainCtrl',function($scope){

 });

Blog Module:

var blog = angular.module('app.blog',[]);

proposal.controller('blogCtrl', function($scope, myDta){
  // This is where I will handle all the logic for blogs. Will have functions calling blog service which will call the server and GET or POST data.
  $scope.prop = myDta;
});

HTML:

<html lang="en" ng-app="app">
 <script type="text/javascript" src="./js/app.js"></script>
 <script type="text/javascript" src="./js/blog.js"></script>
 <script type="text/javascript" src="services.js"></script>

Do you think architecture or structure is good enough to put into production? My app is grow slowly as I will adding a lot more functionality so I want to make sure the structure I create is maintainable and scalable.

1
  • If you want to build a large scale Angular application, start using .component() and .directive() and avoid $scope where possible (since 1.5 its only required for edge cases). And really dont use ngController in your templates at all.
    – rcd
    Commented Apr 30, 2017 at 14:17

2 Answers 2

1
+50

Nop you have something wrong here, if you really expect your code base to grow a lot you should explode the router configuration in each module.

This mean that the module app.blog should declare itself the route /blog and so on.

Same for templates, you should at least have a dedicated subfolder for your module to have something like

  • blog/blog.html
  • bios/bios.html

Because over the time you will have way more than one template by module.

Finaly don't forget that some templates won't depends on functionnality but on components/directive, those should be isolated in specific modules if they aren't specific to only one module.

For production, you usually minify your code to have in the end only one single file to load. This decrease a lot the first loading time of your page.

EDIT : here some example :

app.js

var app = angular.module('app',['ngRoute','app.blog','routeService']);

app.config(function($routeProvider) {
    $routeProvider

        // route for the home page

        .when('/', {
            templateUrl: '/overview.html',
            controller: 'mainCtrl'
        })  // i don' know about this one, maybe move it under blog 
        // or in another module if it's not specific to blog
        .when('/bios', {
            templateUrl : 'bios.html',
            //controller  : 'contactController'
        });





});

blog/blogs.js

angular.module('app.blog',['routeService'])
.config(['$routeProvider', function($routeProvider){

// route for the about page
        $routeProvider.when('/blog', {
            templateUrl : '/blog/blog.html',
            controller  : 'blogCtrl',
            resolve: {

                myDta: function(dataFetch){
                    return dataFetch.getProposals();
                }}
        })

  }])

blog/blog.ctrl.js

angular.module('app.blog').controller('blogCtrl', ...);

Note : Usually every controller / service are splitted in their own file.

0
0

Maybe not an complete answer. But what me really helped was the Angular StyleGuide By John Papa.

Overall it's a great start but I have some remarks:

Controller As

Try using controller as syntax. in particular when using nested views. In this way you can reference variables and functions on a specific controller.

<div ng-controller="BookController as book">
   {{ book.title}}
 </div>

This Keyword

When using controller as syntax the controller needs to use this keyword instead of $scope.

function BookController() {
   var vm = this;
   vm.title= {};
   vm.deleteBook= function() { };

}

Injection

When using minification you will get errors on the injection parameters you need to mannually specify the parameters.

angular
.module('app')
.controller('BookController', BookController);

BookController.$inject = ['books', 'data'];

function BookController(books,data) {}

self executing anonymous functions

Try to give every controller, route, config in a seperated file so you can use self executing anonymous functions. Enclose every controller,route, etc like this example. See this answer for more info.

(function () {
   'use strict';
    angular.module('app').controller('BookController', BookController);
})();

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.