The npm blog has been discontinued.
Updates from the npm team are now published on the GitHub Blog and the GitHub Changelog.
Using Angular’s new improved Browserify support
With the recent release 1.3.14 instantaneous-browserification, Angular introduced better support for those using Browserify. Thank you to everyone who worked on that issue, and especially to Ben Clinkinbeard for his unflagging dedication in getting it in.
In this article, I’ll show you how Browserify can make your Angular apps better.
The problem
Let’s say that you want to use angular-material
in your application… maybe you want to use its <md-autocomplete>
element.
We’ve created an example that does just that.
What scripts do you have to include? Well, you need to include angular
and angular-material
. You also need to know that angular-material
uses both angular-animate
and angular-aria
, so you have to include those too.
<script src="./node_modules/angular-animate/angular.js"></script>
<script src="./node_modules/angular-animate/angular-animate.js"></script>
<script src="./node_modules/angular-aria/angular-aria.js"></script>
<script src="./node_modules/angular-material/angular-material.js"></script>
You’re only using one library, but you have to know about four different scripts and the paths to those scripts.
It would be great if your app only needed to know about angular-material
, and if angular-material
knew about its own dependencies… and that’s one of the things Browserify helps you do.
To do this, we’re going to need to make changes both to angular-material
and to our app.
Changes in a module like angular-material
If you were the maintainer of a module like angular-material
, what changes would you need to make for this to work?
Declare dependencies in
package.json
You’ll need to specify the version of the other module. You should specify this as a range, rather than an exact version of the other module. For example, you could use
1.x
to specify anything in the1
major range. Or you could use^1.3.0
to specify anything higher than1.3.0
in the1
major range."dependencies": { "angular": "^1.3.0", "angular-animate": "^1.3.0", "angular-aria": "^1.3.0" }
Add an
index.js
Browserify will look for the module’s main file. You can either name it
index.js
, or you can add a different name for it in themain
field ofpackage.json
.This file should use the
require
function to let Browserify know which other modules need to be loaded. This should just be the name of the module, as you listed it inpackage.json
. Browserify will figure out what the path to that module’s main file is.You’ll also want to make sure Browserify loads your module’s code. For this, you will need to use the relative path. For example,
require('./angular-material.js')
.Finally, to match the convention for CommonJS set up within Angular, you’ll need to expose the string that people use to load your module. You’ll do this using
module.exports
. Note, this is a convention that Angular uses, and it doesn’t necessarily apply to other front-end projects.require('angular-animate'); require('angular-aria'); require('./angular-material'); module.exports = 'ngMaterial';
Changes in the app
Now that angular-material
plays well with Browserify, we can take advantage of that in our app. Check out the demo to see it all in action.
Install browserify globally
Browserify is a command line tool that you use when building your project. It isn’t loaded when you’re running your app. This means it should be installed globally, not as a dependency of the project.
npm install -g browserify
If you get an error that says EACCES, check out our docs on [fixing permissions](https://docs.npmjs.com/getting-started/fixing-npm-permissions), or just run the command with sudo.
Add
angular-material
as a dependencyYou need a
package.json
file for your application to do this. If you don’t have one, usenpm init
to create one.Then you can just run:
npm install --save angular-material
Note: In the example repo, you’ll see that we use
linclark/bower-material
here instead. That’s because the changes to the module that we made in the last section haven’t been merged in and published to npm yet, so we’re depending on our fork instead.Create your script
Create a file named
entry.js
to hold your script. The important thing to do in your script is to userequire
. For example, for the demo, we start with the following code:var angular = require('angular'); angular .module('autocompleteDemo', [require('angular-material')]) .controller('DemoCtrl', DemoCtrl);
You can see the whole script in the demo.
require
is used twice here. It is used to get theangular
variable, and then it is used again to get the name of the module that the injector will use. Using require in this way makes the dependencies explicit so that Browserify knows that it needs to go fetch the scripts forangular
,angular-material
, and any of their dependencies—angular-aria
andangular-animation
in this case.Bundle up the scripts
Now we run Browserify to bundle all the scripts together into a single file,
bundle.js
.browserify entry.js -o bundle.js
Use
bundle.js
inindex.html
Now that all of the dependencies are in
bundle.js
, we can remove the script tags forangular
,angular-aria
,angular-animate
, andangular-material
and replace them with a single script tag forbundle.js
.<script src="bundle.js"></script>
To wrap it up
You should be able to depend on something without having to know about its dependencies, and about the dependencies of its dependencies. With this change, angular-material
declares its own dependencies, making it easier for you to use it throughout your app.
So next time you are using an Angular module and have to include a bunch of script tags, think about putting in a PR and making things a little easier to bundle up.