Using ng-annotate for min-safe AngularJS

Aaron Frost
InstructorAaron Frost
Share this video with your friends

Social Share Links

Send Tweet
Published 10 years ago
Updated 5 years ago

When you minify your code with a tool like Uglify, the resulting minified file will rename variables. This is a problem for AngualrJS, which uses parameter names to provide injected dependencies. You could use the array notation manually, but no human should ever have to suffer this fate, or you could use ng-annotate with Grunt, and let your helper robots get the job done instead.

[00:01] Let's move on to adding a new plugin called ng-annotate. In the last few steps, one of the thing we did was uglify our JavaScript. Uglification is another word for minification.

[00:11] We compiled it all into one file, app.js inside of our build directory. When we did this, it's cool, but we kind of clobbered the JavaScript, and we need to do a few things to fix it. One of the things we need to do is fix the build saving around our Angular code.

[00:26] What does it mean to be build safe? Let me go ahead and explain it. When we built our app, we created a module named "app," and we added a controller called "Feedback." Inside the "Feedback" controller, we requested three specific dependencies, "$scope", "$http", and "$log".

[00:43] Because of the way "$scope" is spelled, Angular knows where that dependency is and knows how to inject it, and because we spelled "$http" with a dollar in front of it, Angular knows what that dependency is and can inject it, and same with log.

[00:57] If we were to change "$http", if we were to remove something or change it to something besides "$http", Angular wouldn't know how to inject it anymore. It's important that our parameter names don't get changed.

[01:08] When we uglified our code, this is what it looks like now. We have our Angular module "app" with our controller "Feedback," but it renamed our parameters for the sake of minification. It took our "$scope" and called it "a", our "$http" and called it "b", and our "$log" and called it "c".

[01:25] Angular is now in a busted state because it doesn't know hot inject "a", "b", or "c" because they were never declared. There's two ways to fix this, by manually protecting against this kind of build problem or by using ng-annotate. Let me show you how you would do it manually so we can appreciate the benefits we're getting from ng-annotate.

[01:43] In order to build-safe our code, we can use what's called an array syntax. We wrap our controller function in an array, and then we take our three parameters, we're going to copy them and make them strings at the beginning of our array.

[02:02] By doing this, we're protecting our build. The uglification process will not change streams. If we look at our app.js, it didn't change the word "Feedback" because that's in a string. Now that we've build-saved our controller by wrapping in this array, it's not going to go ahead and change these either. It'll still change the parameters to "a", "b", and "c", but because we've wrapped it in this array, Angular will now know how to assimilate that.

[02:29] Let's go ahead and run our grunt build so we can see what it will look like.

[02:37] Now when we look at our app.js, we can see we still have our "Feedback" controller but it's got this build safety around it, so it says, "For 'a', 'b', and 'c', go ahead and inject '$scope', '$http', and '$log'." This is how you manually build-safe your code.

[02:56] A lot of people don't like writing it like this. It takes a lot of effort and some people appreciate the simplicity of writing Angular without the array syntax, and that's where ng-annotate comes in handy. We can use it in our grunt file and add it to our build so that our build will automatically add that build safety into each of our Angular components. Let's go ahead and get it set up.

[03:18] To start, we're going to go ahead and install the ng-annotate plugin for grunt, so we're going to type "npm install grunt-ng-annotate", and we're going to use the "--save-dev" flag so that it saves it for us.

[03:33] Now that we've got that installed, let's load it into our grunt file, so we will just say "ng-annotate", and now it's here. Now that we've done that, let's go ahead and add it to our init config.

[03:48] There's a few ways that we can configure ng-annotate. I'm going to add some options so that it doesn't add double quotes, it adds single quotes, because that's my preference.

[03:58] Now we're going to add a build target for our app. We're going to tell it to look at our specific build files and we're going to have it modify them for us. For the sake of simplicity, I'm going to paste this configuration in.

[04:12] Essentially what I'm saying here is take the app.js, and build it into our "build" directory into a new temp folder, and built it into the app.js. It's going to take each of our files from the source JavaScript directory and put it in this temp directory inside of our build folder.

[04:32] We're then going to take these new temporary files and we're going to use them. Instead of concatenating our files inside the JavaScript folder, we're going to concatenate them from inside the build temp folder. Now the concatenation will take our Angular library and take our new ng-annotated build-safe files from the build temporary directory.

[04:51] We're going to need to do one last thing. At the end of our build, I wanted to go ahead, and clean out, and remove that temporary directory, so I added a new clean target called "temp".

[05:02] Let's add ng-annotate into our build step down below. After we have it clean, let's go ahead and add the ng-annotate, and at the very end we're going to go ahead and have it run our clean temp target, which will clean out the temporary directory.

[05:20] Now at this point we can go ahead and run "grunt build", and you can see it went through all the steps. It ran ng-annotate on our files, it concatenated all of our files, it uglified them, and then it cleaned out the temp directory. If we come up here and we look at our app.js, you can see that it put in that array syntax for us and we're good to go.

[05:46] Our code is now build-safe and ready for us to move on to the next step. There are quite a few things left we still need to do. A lot of them revolve around updating the index to HTML, dealing with our templates and our CSS as well. We'll get to those in the next videos.

egghead
egghead
~ an hour ago

Member comments are a way for members to communicate, interact, and ask questions about a lesson.

The instructor or someone from the community might respond to your question Here are a few basic guidelines to commenting on egghead.io

Be on-Topic

Comments are for discussing a lesson. If you're having a general issue with the website functionality, please contact us at support@egghead.io.

Avoid meta-discussion

  • This was great!
  • This was horrible!
  • I didn't like this because it didn't match my skill level.
  • +1 It will likely be deleted as spam.

Code Problems?

Should be accompanied by code! Codesandbox or Stackblitz provide a way to share code and discuss it in context

Details and Context

Vague question? Vague answer. Any details and context you can provide will lure more interesting answers!

Markdown supported.
Become a member to join the discussionEnroll Today