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.logs 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 watchifyshould benpm install -g watchifyto get the watchify command. If you just install the package you'll getwatchify: command not found