Minification Errors in My AngularJS WordPress Theme

This is the 4th post of a series about building WordPress themes with AngularJS and WP REST API (WP API).

In previous posts (1st, 2nd, 3rd) I’ve covered several topics in AngularJS with a very simple WordPress theme, include:

Module

We registered our application as a module called app to AngularJS. By adding a new attribute ng-app="app" to <html> in header.php, we can run the WordPress site as an AngularJS app. If our app requires other modules to run, we can add them to an array in the second parameter:

Route

With ngRoute when we change the path in our application, other than refreshing the whole page, only part of it (content in ng-view) will get updated. That makes our app a Single Page Application (SPA).

Controller

In the controller functions we set the initial state of a $scope object. For instance, we get a bunch of posts or a single post from WordPress (database) and attach them to the $scope object. We use them in our view with syntax like {{post.title}}. The other usage of controllers is to add behavior (functions) to the $scope object.

ngSanitize and ngBindHtml

When binding raw HTML or special characters (like HTML entities) to the page content, we should pass them via ngBindHtml directive, so ngSanitize module will return the sanitized and properly escaped string on the page.

Custom Directive

We can create custom directives as template tags like get_search_form() in WordPress. We built the searchForm directive and added a function to make it search for posts when the search keyword changed. In the beginning of 2015 I would like to do a code cleanup for the series of tutorials and share a very important concept in AngularJS with you, that is Dependency Injection (DI).

Minification Errors in my AngularJS WordPress theme

To clean up the code I assign the app module to an app variable, other than chaining everything together, I can write the config, controllers and directives in separated blocks. After that I use CodeKit to minify the scripts.js (you can use a free service like this), and use the minified version in my demo theme. But it turns out the minified version of scripts.js causes errors, and the app doesn’t work. To make my scripts.js “minification safe”, there are 2 methods I can use.

Minification errors in browser

Method one: inline array annotation

If we adopt this method, we’ll use a special syntax to write the constructor function of config and controllers. We pass an array whose elements consist of a list of strings followed by the function itself. And you must have noticed, the string elements in the array are exactly the same as the parameters of the function.

Method two: $inject property annotation

This method makes your code more organized and readable. We’ll assign the constructor function to an variable, then assign an array (consists of a list of strings like method one) to the $inject property of this variable.

What does the two methods have in common?

The two annotations are both provided by AngularJS, according to the document, method one is preferred. Though they do have one thing in common: the ordering of the values in the array must match the ordering of the parameters. That means, the names of parameters in the constructor function can be different from the string elements in the array, as long as the ordering is matched. For example:

Just update the scripts.js with one of the annotation above, and minify it again, you’ll eliminate all minification errors!

Dependency Injection does the magic

When I learned step by step with this WordCamp video: Eric Wolfe: Building a WordPress Theme Using AngularJS, it looks like I don’t have to set the data of parameters in the controller functions, I can use them right away, how amazing!

It’s when I read the ng-book later, I knew the magic is done by a design pattern called Dependency Injection. In the AngularJS document, it is described as:

Dependency Injection (DI) is a software design pattern that deals with how components get hold of their dependencies.

The Angular injector subsystem is in charge of creating components, resolving their dependencies, and providing them to other components as requested.

So when we create the constructor function for a component (like controller, config, or directive) in AngularJS, all parameters of the function are “dependencies” – the component depends on them.

Take our theme for example, since one of the purposes of a controller is to set up the initial state of the $scope object, we need to set the $scope object as its dependency.

Dependency annotations

The first annotation we learned from this series of tutorials, is called “implicit annotation”. Which is described in the AngularJS document as “the simplest way to get hold of the dependencies is to assume that the function parameter names are the names of the dependencies.

That’s pretty straight forward, as long as we use the names of the objects / services as the parameter names, e.g. $scope, $http$routeParams, AngularJS will go get them for us. And of course we can reorder these parameters as we want, AngularJS only care if the names are right, the order doesn’t matter at all.

Oops! Minifiers change the names of the parameters

Even we don’t know how exactly the JavaScript minifiers/obfuscators work, but it’s obvious that they remove spaces and line breaks, and also rename the parameters and variables, to get the scripts clean (ugly) and shorter.

Now we realize the minification errors are fairly reasonable – the parameters are renamed by the JavaScript minifiers. That’s how they break our code.

Why those 2 “minfication safe” methods work

The method one “inline array annotation”, is the way AngularJS uses to keep track of the names of parameters. You can do the test by paste a sample array to an online Javascript minifier, like this:

You’ll see that if the element is a string, it won’t be renamed, the “$scope” is still “$scope”, “$http” is still “$http”, and so on.

So AngularJS can map the function parameters to the array elements, and figure out what exactly objects they should be. That’s also why the “ordering” becomes so important – it’s the key to make the mapping right.

As to the “$inject property annotation”, the syntax should be self-explanatory that it won’t be affect by JavaScript minifiers.

Download the updated theme

Now you can get the updated theme from my Github repo as a zip file. I hope you understand AngularJS better with this tutorial, or at least know how to eliminate minification errors in your scripts.

See you in next tutorial!

I’m a senior web developer helping clients build their websites to grow businesses. Currently I’m based in Taipei, Taiwan.

I write things about WordPress, AngularJS and life. Whenever you’d like to find someone to talk about these topics, just get in touch!

One Comment

Submit a comment

Submit a comment

Your email address will not be published. Required fields are marked *