flimsy flimsy - 1 month ago 25
AngularJS Question

Lazy loading Angular modules with Webpack

I'm trying to get lazy-loaded Angular modules working with Webpack, but I'm having some difficulties. Webpack appears to generate the split point correctly, because I see a

1.bundle.js
getting created that contains the code for the child app, but I don't see any request for
1.bundle.js
when I load the page, and the child app doesn't initialize. The
console.log
never seems to fire, and it doesn't even appear to get to the point where
$oclazyload
would initialize the module.

There are a few points where I am confused.

1) Will webpack make the request to the server, or do I have to load the second bundle manually? (I've tried both, and neither works)

2) If I do need to load the bundles manually, in what order should they be loaded?

3) The third argument to
require.ensure
supposedly lets you control the name of the bundle, but the bundle is named
1.bundle.js
no matter what string I pass.

4) Why can't I step through the code inside the
require.ensure
block in the debugger? When I do so I end up looking at this in the Chrome source view:

undefined


/** WEBPACK FOOTER **
**
**/


(Code Below)

Main entry point code:

'use strict';

import angular from 'angular';
import 'angular-ui-router';
import 'oclazyload';


angular.module('parentApp', [
'ui.router',
])
.config(['$urlRouterProvider', '$locationProvider', ($urlRouterProvider, $locationProvider) => {
$urlRouterProvider
.otherwise('/');

$locationProvider.html5Mode(true);
}])

.config(['$stateProvider', ($stateProvider) => {
$stateProvider
.state('child-app', {
url: '/child-app',
template: '<child-app></child-app>',
resolve: {
loadAppModule: ($q, $ocLazyLoad) => {
return $q((resolve) => {
require.ensure(['./child-app/app.js'], (require) => {
let module = require('./child-app/app.js');
console.log(module);
$oclazyload.load({name: 'childApp'});
resolve(module.controller);
});
})
}
},
controller: function() {
}
})
}]);


Child app:

'use strict';

import childAppTemplateURL from '../templates/child-app.html';
import childAppController from './controllers/childAppController';

export default angular.module('parentApp.childApp', [])

.component('applicationListApp', {
templateUrl: childAppTemplateURL,
controller: childAppController
});

Answer

The problem was unrelated to the require.ensure implementation. It was caused by some weirdness in the way ocLazyLoad is packaged (https://github.com/ocombe/ocLazyLoad/issues/179). The fix in my case was simple, I just added 'oc.lazyLoad' to the module dependencies.

angular.module('parentApp', [
  'ui.router',
  'oc.lazyLoad'
])

To answer two of my own questions, Webpack does indeed make a request to the server for the bundle, and you do not have to manually load the bundle. One gotcha that really confused me: the resolve block will fail silently if it contains a promise that won't resolve. In my case $ocLazyLoad.load() was failing, but there was no indication of the failure. The only clue was that the state provider wasn't adding the <child-app></child-app> markup to the DOM, which meant that it was actually initializing the state.

Comments