1. 7
    AngularJS with Webpack - Requiring Templates
    2m 48s
⚠️ This lesson is retired and might contain outdated information.

AngularJS with Webpack - Requiring Templates

Kent C. Dodds
InstructorKent C. Dodds
Share this video with your friends

Social Share Links

Send Tweet
Published 9 years ago
Updated 2 years ago

With Angular, most of the time you're specifying a templateUrl for your directives and states/routes. This means you need to make sure that you're loading in these templates into the $templateCache for your tests and production. Oh, and don't forget to update all your URLs whenever you move the files around! When you add in Webpack and the raw-loader, you don't need to do this anymore. Simply require the html file and your work is done!

[00:01] When you're using Webpack, you have a really huge benefit that comes with all of your resolve statements being executed before your files are loaded into the browser. One thing that is insanely powerful is instead of using templateUrl, you can use template everywhere.

[00:18] You don't need to worry about the templateCache or XHRs firing off to go get your templates. The way that this works is you simply require the file there. You're done. You do need to add a loader, but what's really nice about this is this makes things a lot more modular.

[00:36] We could move these two files anywhere together. This component would still work. We wouldn't have to change the templateUrl to be pointing to the correct place wherever you move the file. This is a huge win that Webpack gives us.

[00:50] If we were to save this and refresh, we're going to get an error right here. You need an appropriate loader to handle this file type. Webpack doesn't understand what on Earth this is talking about.

[01:01] To accomplish this, we need a new loader. We'll npm install the raw loader. We'll add that as a dev dependency. We'll go to our Webpack config. We'll add a new loader here. Anything that ends in an HTML, we want it to use raw or the raw loader. Pro tip. This and this are the same thing. If you don't want it to be so verbose, then you just leave off the "loader."

[01:32] Now, if we restart our dev server, everything should work properly. We refresh. Everything is good to go. You no longer need to use templateUrl or template anything. In fact, with something so simple as this, we don't even need to reference that. Because this application is using ES6, we could just as easily put our template right there. No worse for wear.

[02:00] It depends on your style. Obviously, you're not going to want to do this if your template is very large, but as it is, it works really well just to use the template string with the backticks so we have multilines. That is loading your HTML, getting rid of your templateUrl, and just using template.

[02:23] This really resolves a lot of the concerns with the HTTP backend when you're testing to make sure that you're loading stuff with ng-to-JS HTML loader plugins for Karma or whatever. You don't need to worry about that anymore with Webpack. That's another awesome thing that Webpack brings to the table with Angular.

John
John
~ 9 years ago

how does it handle ng-include in the view?

Kent C. Dodds
Kent C. Doddsinstructor
~ 9 years ago

You can get ng-include to work with webpack, you'd just need to pre-load the $templateCache with all the templates you want by hand which shouldn't be a big deal.

However, I would highly recommend against using ng-include and instead use an element directive with isolate scope. It is impossible to know the API to a template using ng-include but with an isolate scope directive, you define your API so from a maintainability/reasonability standpoint, you're much better off.

John
John
~ 9 years ago

got it, thanks Kent

Sander
Sander
~ 9 years ago

It seems that in order to have webpack require a referenced image from a directive template (e.g. <img src="../../logo.png" />), html-loader is needed instead of raw-loader.

Kent C. Dodds
Kent C. Doddsinstructor
~ 9 years ago

Very good point! Thank you for correcting me there. I don't actually use img tags in my app at all so it works fine for me to use the raw-loader. But most people should probably be using the html-loader.

Elia
Elia
~ 8 years ago

I've tried to use raw loader for my component's templates, but (sometimes) i get this error:

In Chrome dev tools: http://localhost:8080/%3Cdiv%20class='page-header'%3E%20%20%3Ch1%3E%7B%7B%2…%20%20%20%20%20%3C/div%3E%20%20%20%20%3C/div%3E%20%20%3C/form%3E%3C/div%3E 414 (Request-URI Too Large)

In console: ENAMETOOLONG

How i can fix it? Thanks

Kent C. Dodds
Kent C. Doddsinstructor
~ 8 years ago

That's probably happening because you're still using templateUrl rather than template

Elia
Elia
~ 8 years ago

You right! I've found that i use it in my router. I've changed my components template, but not the router. Now works, but i've an error: "jQuery is not defined". Strange because i don't use it, maybe it's some package. Webpack can't include it automatically if it's a dependency?

Elia
Elia
~ 8 years ago

I've figured it out installing jquery with npm and adding this loader:

test: /bootstrap/js//, loader: 'imports?jQuery=jquery'

J.C. Francis III
J.C. Francis III
~ 8 years ago

What do the package.json scripts look like for Windows? I can't get the build script working.

Kent C. Dodds
Kent C. Doddsinstructor
~ 8 years ago

Yeah, sorry. Try installing and using cross-env for the build script:

npm install -D cross-env

Then update build to:

"build": "cross-env NODE_ENV=production webpack && cp app/index.html dist/index.html"

Note, I edited the script a bit because you don't need node or to point directly to node_modules/.bin/webpack.

Good luck!

J.C. Francis III
J.C. Francis III
~ 8 years ago

Thanks this worked. I used xcopy [source] [destination] /Y to cp. Thanks again.

Tim
Tim
~ 8 years ago

Followed steps in this video but I'm getting a termial error when I ran webpack. Any ideas?

ERROR in ./scripts/Directive/socialMediabuttons.js Module not found: Error: Cannot resolve 'file' or 'directory' ./components/social-media-buttons.html in /app/scripts/Directive resolve file

Kent C. Dodds
Kent C. Doddsinstructor
~ 8 years ago

That error would seem to indicate that webpack is unable to find a file in /app/scripts/Directive/components/social-media-buttons.html. If the file is actually there, my guess is that you may be setting your context incorrectly with the leading / in /app (it needs to be a full path, but it you probably don't mean the app directory in your root directory).

Good luck!

Joseph
Joseph
~ 8 years ago

I'm getting the following error:

Module parse failed: /Users/joe/Dev/angular-webpack/app/directives/kcd-hello.html Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected token (1:0)````

In my webpack config: 

modules: { loaders: [ { test: /.js$/, loader: 'babel', exclude: '/node_modules' }, { test: /.html$/, loader: "raw", exclude: '/node_modules' } ] }


And in my directive:

module.exports = function (ngModule) { ngModule.directive("kcdHello", function () { return { restrict: 'E', scope: {}, template: require('./kcd-hello.html'), controllerAs: 'vm', controller: function (){ var vm = this; vm.greeting = 'hello webpack' } } }) }

Any ideas why i'm still getting the error? My template is just a simple div with {{vm.greeting)).  I also tried html-loader, but that failed too. 
Joseph
Joseph
~ 8 years ago

So after tearing my hair out for a while, i think this was the issue. Webpack config should have been:

module: {
        loaders: [ ...

not:

modules: {
        loaders: [....
Kent C. Dodds
Kent C. Doddsinstructor
~ 8 years ago

Sorry to hear that you had that trouble! I recommend that you give webpack-validator a look. You would have caught that spelling error with webpack-validator :-)

Markdown supported.
Become a member to join the discussionEnroll Today