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()
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 --save
npm > Checking for package npm > LOL DOWNLOADING THE WHOLE INTERNET NOW
npm > STILL DOWNLOADING
npm > 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