We want to learn:
- What is NPM
- Dependencies installation
- Initially package.json for your project
- Project workflow:
- Begin writing code
- Require dependencies
- Bundling
It's the package manager for Javascript. Think Python's PyPi for Javascript.
That's about it!
npm is bundled with node or io.js. Get one of those and you're golden.
brew install node
Each project must be packed by a package.json
to work well with the npm
ecosystem and browserify workflow. It is standard for any modern Javascript
project to include a package.json
at its root.
npm has a helper function to initialize this for your project. First, let's make a new project
mkdir ./learn-browserify
And initialize it with a package.json
cd ./learn-browserify
npm init
You'll be asked a bunch of questions. Answer as you wish, and leave defaults
where you're not sure. You should now have a package.json
in your directory
that looks something like this:
{
"name": "learn-browserify",
"version": "1.0.0",
"description": "",
"main": "index.js",
"author": "",
"license": "ISC"
}
Self explanatory for the most part. Maybe you're not sure what main
means.
Basically, if someone require()
's your project then the file here (index.js
)
will be the entry point for finding the export.
First, download the provided index.html as a starter. It contains some essential HTML that'll be used by our app, and a link to our bundled Javascript application.
Let's begin writing our first npm-enabled module. We'll use index.js
because
that's what our main
file is. Open that up in your favourite editor.
First, some scaffolding to get out of the way. Let's have our app bind to the
select list with id region
to run a function when changed.
# index.js
var App = {
handleChange: function(ev) {
var e = ev.currentTarget
console.log("Selected", e.options[e.selectedIndex].value)
},
blastoff: function() {
var elem = document.getElementById("region")
elem.addEventListener("change", this.handleChange.bind(this))
}
}
App.blastoff()
Let's build that out, and run it. You'll notice our index.html references
index.js
and we're not using browserify -- yet!
Open index.html
in your browser and tinker with the drop down while having
Chrome Inspector open (CMD + OPTION + i). You'll see it console.log
s your
selected value.
BTW: You can run a simple server in Python using:
python -m SimpleHTTPServer [port]
Ok, ok. Our app is simple, but now we're going to need some dependencies, and we're going to want to bundle those up into a single file.
We're going to make our app hit the G API each time the select list is changed, and then return a bunch of tours, and their links for that region. Nothing fancy, but workshop, yo.
So, we're going to need to make AJAX requests. Now, some of you might think we can just use jQuery. But not for this example! We're hipster cool here and we need to use a smaller library that focuses on just doing HTTP requests, and that's it
My preference is superagent
The npm page is a great way to understand what a package does, and the site in general is a neat tool for searching. I also like GitHub, as you get a better view of activity, forks/stars and issues.
cd ./learn-browserify # in case you're not already there.
npm install --save superagent
Cool! It worked. What does --save
mean by the way?
It's just a simple shortcut to adding the installed version of superagent
into
your package.json
. Open it up, it's there now. Magical.
What does dependencies
mean exactly? Well, it's like pip
requirements. When
we run npm install
in a project with a package.json, all dependencies will be
installed.
Ok, time to get serious. Let's adjust our code. We're going to require
superagent and make it do an API request.
var request = require('superagent')
function makeApiCall(region, callback) {
request
.get("https://rest.gadventures.com/tour_dossiers")
.set("X-Application-Key", "live_b9703931efc7980f33195ba893de8c4a6834877b")
.query({'geography__region': region})
.end(callback)
}
var App = {
displayResults: function(err, response) {
console.log(response)
},
handleChange: function(ev) {
var e = ev.currentTarget
var region = e.options[e.selectedIndex].value
makeApiCall(region, this.displayResults.bind(this))
},
blastoff: function() {
var elem = document.getElementById("region")
elem.addEventListener("change", this.handleChange.bind(this))
}
}
App.blastoff()
And now we have to bundle it. Let's use browserify
. First, we install it
npm install --save-dev browserify
Hmm, --save-dev
? Just like --save
except it fills out devDependencies
because browserify is needed for development of this project, but not
necessarily to run it in the wild.
And bundle:
browserify ./index.js -o bundled.js
Open up bundle.js
and you'll see it's a big mess of code. Some of it may look
familiar to you! Let's adjust index.html
to look for bundled.js
rather than
index and re-run it.
Browserify is smart enough to follow the dependency path and ensure all requirements are bundled into your code.
That's cool, because there's a tool for that. Just use watchify
! Which is like
browserify, but it watches for changes on your application.
npm install watchify
# same API as browserify
watchify ./index.js -o bundled.js -v
(If we have time in this lunch and learn) Try parsing the results from the API
into the HTML. Perhaps you can use lodash
from npm and it's template
function to render and append templates to the DOM. Try it out!
There are a few ways you can do this. What eCommerce does is run browserify on
each deploy (via a collection of gulp.js
tools) to bundle that app and throw
it into a static distribution directory.
Then, it's just included in templates as you would any other Javascript.
<script type='text/javascript' src='{% static "apps/dist/myapp.js" %}'></script>
More details can perhaps come at another lunch and learn, where we can focus our scope on that!
npm install watchify
should benpm install -g watchify
to get the watchify command. If you just install the package you'll getwatchify: command not found