Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

refactor large AngularJS module config into separate files

Tags:

angularjs

Problem: Large config()

The config of my AngularJS app is growing quite large. How would you refactor the following into separate files?

// app.js
angular.module('myApp')
    .config(function($urlRouterProvider, $stateProvider, $httpProvider) {
        // Configure routing (uiRouter)
        $urlRouterProvider.when('/site', '/site/welcome');
        $stateProvider.state('main', ...
        ...

        // Configure http interceptors
        $httpProvider.interceptors.push(function () {              
            ...
        });
    });

Option 1. Multiple config()s

I know that I can have multiple config()s and place them in separate files like this:

// app.js
angular.module('myApp');

// routerConfiguration.js
angular.module('myApp')
    .config(function($urlRouterProvider, $stateProvider) {
        // Configure routing (uiRouter)
        $urlRouterProvider.when('/site', '/site/welcome');
        $stateProvider.state('main', ...
        ...

// httpInterceptorConfig.js
angular.module('myApp')
    .config(function($httpProvider) {
        // Configure http interceptors
        $httpProvider.interceptors.push(function () {              
            ...
        });
    });

What I do not like about this, is that in the original app.js, there is no way of getting an overview of what is run at startup.


Option 2. Inject something

I would prefer to do something like this, because it would be easier to see what is configured, directly in the app.js. However I know that this is not possible, since we cannot inject services into config().

Can I use providers to solve this? Is there a better way?

// app.js
angular.module('myApp')
    .config(function(routerConfig, httpInterceptorConfig) {
        routerConfig.setup();
        httpInterceptorConfig.setup();
    });

// routerConfig.js
angular.module('myApp')
    .factory('routerConfig', function($urlRouterProvider, $stateProvider) {
        return {
            setup: function() {
                // Configure routing (uiRouter)
                $urlRouterProvider.when('/site', '/site/welcome');
                $stateProvider.state('main', ...
                ...
            }
        };
    });
});

// httpInterceptorConfig.js
angular.module('myApp')
    .factory('httpInterceptorConfig', function($httpProvider) {
        return {
            setup: function() {
                // Configure http interceptors
                $httpProvider.interceptors.push(function () {              
                ...
            }
        };
    });
});
like image 423
Joel Avatar asked Aug 21 '14 10:08

Joel


2 Answers

You can use .constant as a dependency in a .config, so you could use the config declaration as a manual composition root. For example:

angular.module('myApp')
    .config(function($urlRouterProvider, $stateProvider, $httpProvider,
                     routerConfig, httpInterceptorConfig) {
        routerConfig($urlRouterProvider, $stateProvider);
        httpInterceptorConfig($httpProvider);
    });

// routerConfig.js
angular.module('myApp')
    .constant('routerConfig', function($urlRouterProvider, $stateProvider) {
        ...
    });

// httpInterceptorConfig.js
angular.module('myApp')
    .constant('httpInterceptorConfig', function($httpProvider) {          
        ...
    });

Drawbacks to this approach are that you have to inject all of your config dependencies into the root config function, then manually inject them into your constant config functions. If you have a lot of different config functions, this could get messy. It can also look kind of like your config functions are having dependencies injected by Angular, but in fact you are doing it manually. You would need to make sure you remember to do the manual wiring every time you add a new config function.

My preferred approach is just to have a folder called "config" containing exclusively config calls.

like image 61
Alex Avatar answered Nov 18 '22 01:11

Alex


I would look at browserify

It allows you to use markup to require modules in your javascript.

This would allow you to break up your config into multiple files while keeping them together (see example).

browserify compiles your javascript into a single bundle.js by recursively tracing the requires from your main javascript file.

You then only need to include <script src="bundle.js"></script> on your index.html

Short Example

Javascript

'use strict';

require('angular/angular');
require('angular-ui/ui-router');

var app = angular.module('vw', ['ui.router', 'myApp.feature1', 'myApp.feature2'])
                 .config(require('./config/route'))
                 .config(require('./config/httpProvider'));

angular.bootstrap(document, ['myApp']);

File Structure

  • myApp
    • config
      • route.js
      • httpProvider.js
    • myApp.js
    • index.html
like image 41
Malkus Avatar answered Nov 18 '22 01:11

Malkus