AngularJS and Webpack Integration

All we need is an easy explanation of the problem, so here it is.

I am looking for some help with using webpack for a large AngularJS application. We are using folder structure based on feature (each feature/page has a module and they have controllers, directives). I have successfully configured webpack to get it working with Grunt, which produces one single bundle. I want to create chunks as its going to be a large app, we would like to load modules (page/feature) artifacts asynchronously.

I am going through some of the webpack example to use 'code splitting' using require([deps],fn ) syntax. However I couldn’t get the chunks lazy-loaded. First of all, I don’t know where exactly, I would need to import these chunks before AngularJS would route the user to next page. I am struggling to find a clear separation of responsibility.

Did someone point me to an example AngularJS application where webpack is used to load controllers/directives/filters asynchronously after each route?

Few of the links I am following:
Should I use Browserify or Webpack for lazy loading of dependancies in angular 1.x
https://github.com/petehunt/webpack-howto#9-async-loading
http://dontkry.com/posts/code/single-page-modules-with-webpack.html

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

Sagar Ganatra wrote a helpful blog post about code splitting.

Suprisingly code splitting isn’t really supported by angular’s module system. However, there is a way to achieve code splitting by saving a reference to angular’s special providers during the config-phase.

[…] when Angular initializes or bootstraps the application, functions – controller, service etc,. are available on the module instance. Here, we are lazy loading the components and the functions are not available at a later point; therefore we must use the various provider functions and register these components. The providers are available only in the config method and hence we will have to store a reference of these providers in the config function when the application is initialized.

window.app.config([
    '$routeProvider',
    '$controllerProvider',
    '$compileProvider',
    '$filterProvider',
    '$provide',
    function ($routeProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) {

        $routeProvider.when('/login', {
            templateUrl: 'components/login/partials/login.html',
            resolve: {
                load: ['$q', '$rootScope', function ($q, $rootScope) {

                    var deferred = $q.defer();

                    // lazy load controllers, etc.
                    require ([
                        'components/login/controllers/loginController',
                        'components/login/services/loginService'
                    ], function () {

                        $rootScope.$apply(function () {
                            deferred.resolve();
                        });

                    });

                    return deferred.promise;
                }]
            }
        });


        //store a reference to various provider functions
        window.app.components = {
            controller: $controllerProvider.register,
            service: $provide.service
        };

    }
]);

Now inside your loginController for instance you write

app.components.controller('loginController');

to define your new controller lazily.

If you want to lazy-load your templates too I recommend to use the ui-router. There you can specify a templateProvider which is basically a function to load templates async

Method 2

This is a quote from
https://github.com/webpack/webpack/issues/150

webpack is a module bundler not a javascript loader. It package files from local disk and don’t load files from the web (except its own chunks).

Use a javascript loader, i. e. script.js

var $script = require("scriptjs");
$script("//ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js", function() {
  // ...
});

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply