npm + Browserify 

=
Great Success

This has been the best conference ever

because....

Look who I met!

Who is this person?


I'm @robashton



  • Ex Enterprise developer (C#, JS, etc)
  • Now doing Erlang and JS
  • I've worked on a lot of large JS projects

What have I used JS for?


2D Games
3D Games
Enterprise Dashboards
Enterprise Configuration UIs
Enterprise enterprise enterprise

What have I tried?


Backbone
Angular
Ember
+
RequireJS
Bower

But I'm not going to talk about any of these today

The general problem(s)


Where did this function come from?


 doSomethingAwesome()

Which order do I need to include these files?


<script type="text/javascript" src="main.js"></script>
<script type="text/javascript" src="somelib.js"></script>

Where is my entry point?

or

The $(document).ready problem

NPM


  • Node Package Manager

Written for server-side code



Let's do a quick demo so we know how this works

 recap


  • npm is a command line tool
  • it is installed as a part of nodejs

In and out


Exporting from a file
module.exports = someObjectOrFunction 

Importing into a file
var something = require('./something.js') 

And we have


Relative files
require('./somefile.js') 

Modules from node_modules
require('somemodule') 



Why not use this 

for client-side code too?

Well - Why not?


It's synchronous
It's going to involve a build step
It'll make debugging harder

Well..


You always end up with a build step anyway
(Tests, JSLint, Asset Management (css/etc), compression)


So let's take the hit.




So what does this look like?



(demo)


npm install -g browserify

Recap


  • Browserify packages our JS for us
  • We can include templates in this process via transforms
  • Browserify can shrink-wrap modules from NPM
  • Browserify is a hack, but it's a good hack


Source maps



Give us the ability to debug our original JS :-)


browserify -d -o ./out.js

Modules shown



domready
mustache
brfs



Suggestion #1

Single entry point, 'app.js'



Suggestion #2


Use a routing library to kick off individual pages

Magic


 var LocationBar = require('location-bar')
   , navigation = new LocationBar()
   , Index = require('./index')
   , Cats = require('./cats')

  navigation.match(/^$/, function() {
    changeToView(Index)
  })
  navigation.match(/^cats%/, function() {
    changeToView(Cats)
  })




Suggestion #3

Feature folders, not pattern folders

Instead of



/views
 cats.html ponies.html unicorns.html /controllers cats.js ponies.js unicorns.js /models cats.js ponies.js unicorns.js

Consider


/ponies
   index.js
   pony.js
   template.html
/unicorns
   index.js
   unicorn.js
   template.jsx
/cats
   index.js



Suggestion #4

Bundle your assets from feature folders



(consider "component", 
but Make also works well)

https://github.com/component/component )
( http://www.gnu.org/software/make )

Make


CSS = $(wildcard "widgets/*.css")

app/style.css: $(CSS) cat $(CSS) > app/style.css

etc



Suggestion #5

Avoid relative paths for dependencies 

Relative paths


require('../../somewidget')



Every relative path dependency 

is a module waiting to get out





Suggestion #6

Everything is a self contained module

The best module


The best module is one that simply exports a single function that takes in a dom element and some configuration
then raises events when stuff happens


How does it do that? You don't care.

A module



package.json
index.js
lib/item.js
lib/morecode.js
assets/somemarkup.html
assets/style.css



Suggestion #7

Avoid deep dependencies

Don't you just hate it when



npm install anicelibrary --savenpm > Checking for package
npm > LOL DOWNLOADING THE WHOLE INTERNET NOWnpm > STILL DOWNLOADINGnpm > LOL

If I have to download the internet to use your module, 
I'm going to find another module



Suggestion #8

Avoid large dependencies

What is large?



  • Can I read the source code in a single sitting?
  • Can I see how it works easily?
  • If the maintainer runs away, can I easily rewrite it/fix it?




Suggestion #9

Take ownership of your dependencies




Suggestion #10

React makes a fine view engine
(except when it doesn't)

and it doesn't take over your app


 var React = require('react')
   , Widget = require('./lib/widget.jsx')

 module.exports = function(element, cfg) {
    React.renderComponent(Widget(cfg), element)
 } 

Modules can use whatever 

makes sense for them


Mustache/React/Handlebars/EJS/etc

But your team will likely pick one and use it, which is fine

Frameworkless


  • Frameworkless doesn't mean not using other people's code
  • Frameworkless doesn't mean re-inventing the wheel
  • Frameworkless is about enabling flexibility
  • Frameworkless is about POWER

With great power comes great responsibility, etc

Questions?

I have some time before my taxi....

NPM and Browserify

By Rob Ashton

NPM and Browserify

  • 3,214