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.
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.
got it, thanks Kent
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
.
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
.
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
That's probably happening because you're still using templateUrl
rather than template
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?
I've figured it out installing jquery with npm and adding this loader:
test: /bootstrap/js//, loader: 'imports?jQuery=jquery'
What do the package.json scripts look like for Windows? I can't get the build script working.
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!
Thanks this worked. I used xcopy [source] [destination] /Y to cp. Thanks again.
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
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!
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.
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: [....
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 :-)
how does it handle ng-include in the view?