teux / ng-cache-loader

Webpack loader to put HTML partials in the Angular's $templateCache.
83 stars 15 forks source link

404 template not found #29

Closed bostrom closed 7 years ago

bostrom commented 7 years ago

Hi!

I've tried to fiddle around with the options for some time now, but I just can't seem to get this ng-cache-loader to work properly. I always end up getting a 404 in the browser from angular trying to async-load the template instead of fetching it from the $templateCache. Here's my test setup:

Controller, using RequireJS format:

define(['angular', 'ng-cache-loader?module=app.test!../templates/test-partial.tpl'], function(angular) {
    angular.module('app.test', [])
        .controller('testCtrl', ['$templateCache', function TestCtrl($templateCache) {
            // putting it into cache manually works! but we're not doing that now
            // $templateCache.put('test-partial.tpl', require('../templates/test-partial.tpl'));

            // this outputs undefined
            console.log($templateCache.get('test-partial.tpl'));
        }]);
});

Template:

  <ng-include src="'test-partial.tpl'"></ng-include>

Looking at what the ng-loader generates:

var angular = window.angular, ngModule;
try {
  ngModule = angular.module(["app.test"])
} catch (e) {
  ngModule = angular.module("app.test", [])
}
var v1 = "<div>Test</div>\n";
var id1 = "test-partial.tpl";
var inj = angular.element(window.document).injector();
if (inj) {
  inj.get("$templateCache").put(id1, v1);
} else {
  ngModule.run(["$templateCache", function(c) {
    c.put(id1, v1)
  }
  ]);
}
module.exports = v1;
//////////////////
// WEBPACK FOOTER
// ./~/ng-cache-loader?module=app.test!./src/app/test/templates/test-partial.tpl
// module id = 499
// module chunks = 0

The generated code seems correct alright, but still the browser tries to load the template asynchronously: angular.js:8661 GET http://localhost:8000/test-partial.tpl 404 (Not Found).

As noted above, the $templateCache itself works if I inject it into the controller and put the template into the cache! But querying the $templateCache for the template loaded by ng-cache yields undefined.

Am I missing something? Is there some other way to debug this?

bostrom commented 7 years ago

Ok, so I debugged some more and it seems that the execution is ending up in the catch branch of

try {
  ngModule = angular.module(["app.test"])
} catch (e) {
  ngModule = angular.module("app.test", [])
}

i.e. not finding, but re-defining the module that should already exist.

This led me to believe that (a) the loader is using a different angular than the one required into my module definition or (b) my own module is not initialized by the time this code is executed.

As it turned out, the answer was quite simple. Since the RequireJS AMD format requires all dependencies up front before any angular code has been executed, this loader's angular module is created before my own module is created. When the execution comes to my module and controller, it overwrites the loader's module, apparently along with the cached templates.

The solution was to let the loader create its own module "app.templates" and include that in any of my own modules that needs to use cached templates.

Perhaps this is quite the edge case, but it wouldn't hurt to take not of this in the README.