# MVC Module Magic
### App Structurizer, Build Easifier, ### & Middleware Magician
# MVWTF Module Magic
### App Structurizer, Build Easifier, ### & Middleware Magician
# Alex Sexton ##   * Senior UI Developer @ Bazaarvoice * Modernizr and jQuery/yayQuery team member * yepnope.js, Jed, MessageFormat.js
## Modules are not new
function Module () {
            return {
              someStuff: { ... }
            };
          }
          

So what do they have to do with my MVWTF apps?
![img/brain.jpg](img/brain.jpg)
Your need for modules is directly related to how much of your app you can hold in your head at once.
The *MVWTF* pattern is appealing for large applications and encourages code reuse & separation of concerns.
# In other words
### Modules and MVWTF Apps ### *were made for each other*
# App Structure
## All too common
|+ App
           |- app.js
           |- controllers.js
           |- models.js
           |- views.js
           |- index.html
          

### *Dependency management hell*
## How about a *module per file*?
## Option 1
var UserModel = require('Models/User');
            var UserView  = require('Views/User');
            
Which results in this file structure
|+ App
             |+ Models
              |- User.js
             |+ Views
              |- User.js
            
## Option 2
var UserModel = require('User/Model');
            var UserView  = require('User/View');
            
Which results in this file structure
|+ App
             |+ User
              |- Model.js
              |- View.js
            
## Option 3
var UserModel = require('UserModel');
            var UserView  = require('UserView');
            
Which results in this file structure
|+ App
             |- UserModel.js
             |- UserView.js
            
## Now it's much easier to find things. *promise*.
# *perks*.
You can *find* your code.
## Code Reuse
require(['util/A'], function (A) {
            A.hi = 5;
          });
           
          // The same instance
          require(['util/A'], function (A) {
            A.hi === 5 // true
          });
           
          // Or create new instances if you want!
          
## Debugging
There was an error in /util/A.js on line 65.
## Debugging but Worse
There was an error in /built-app.js on line 19823.
## Anonymous defines From
define('some/module', function () {
              ...
            });
            
## Anonymous defines To
define(/* just_use_the_filename, */ function () {
              ...
            });
            
When you no longer *require* a file. It is no longer requested or included.
#### performance++
## Decoupled Mapping Alias modules
({
              "paths" : {
                "underscore" : "lodash"
              }
            })
            

require(['underscore'], function (_) {
              _.isLodash === true
            });
            
## Decoupled Mapping Lose ugly paths
({
              "paths" : {
                "template" : "../../static/template"
              }
            })
            

require(['../../static/template/base'], ...);
            // vs.
            require(['template/base'], ...);
            
## Hierarchy
With this file/folder structure
|+ App
             |- jquery.js
             |+ jquery
              |- ui.js
              |+ ui
               |- draggable.js
            
## Hierarchy
The names can still be decent
require(['jquery'], ...);
            
## Hierarchy
The names can still be decent
require(['jquery/ui'], ...);
            
## Hierarchy
The names can still be decent
require(['jquery/ui/draggable'], ...);
            
In the end, you're left with *easily traversable* files that describe their contents, and most importantly, each maintain their own dependencies.
## Templates are treated as dependencies
## I'm so tired of this
...
            </div>
            <script type="text/tmpl" id="someTmpl">
              {{data}}
            </script>
            <script type="text/tmpl" id="someTmpl2">
              {{data}} 2
            </script>
            </body>
            
Unless you heavily cache your html payload and need dynamic templates at runtime, you're *hurting performance*.
## Minimally, pull in text
// Ajax'd during development,
            // Built as a string in production.
            require(['text!tmpl/one'], function (tmplTxt) {
              // compile and register template here.
            });
            

Better ways than this to come.
## Styles can be dependencies of templates as well
## Same goes for template helpers and UI Messages
# An *AMD* Tangent
## I prefer *AMD* and I specifically use RequireJS
I think it's the best solution for modules on the web that we currently have.
The web is *async*.
The plugin system is killer. *Seriously.* I'll show you in a bit.
I think it's fine as a *compilation target* if you hate the syntax.
But I think a unified target is ideal.
Ember does a good job of AMD as a compilation target with *Ember.amd.js*
# FUD | Collisions
There are well established ways to support AMD in every comination of systems.
Check out [github.com/amdjs](https://github.com/amdjs)
# FUD | Boilerplate
AMD actually requires less characters/lines than the popular alternatives.
var x = require('x');
            var y = require('y');
            var z = require('z');
            // vs.
            require(['x', 'y', 'z'], function (x,y,z) {

            });
            

Not to mention, browser-side code needs minimally an IIFE to not leak.
Use.js helps with unmodified source of modules that do not use AMD. I prefer to just add it. *It's easy™.*
Build.sh has to go away. We need a complex dependency management solution.
I'm glad it's here now, though, because script-tag soup is awful
I think our dependency management tools shouldn't require load time preprocessing.
but if you want to enhance it at load time, that's fine
I think our dependency management shouldn't *require* us to need to run other languages.
I think our dependency management shouldn't force us to manage dependencies outside of our code.
you'll forget/get it wrong.
ES *Harmony Modules* look cool. But aren't currently viable/stable. Use those when they are.
I have a lengthy blog post on [my thoughts on AMD](http://alexsexton.com/blog/2012/03/my-thoughts-on-amd/).
So from now on, I'm gonna use *AMD* in these examples.
Nearly everything is possible via other module systems via load time precompilation, but my examples are already implementable in require.js, etc.
## My new puppy: *batman*
## My new puppy: *batman*
## My new puppy: *batman*
## My new puppy: *batman*
## My new puppy: *batman*
# AMD Plugins
## *Transparent Middleware* Think Connect for node, but for your modules
## How plugins work
Require a module
Modify or change the module
Return the result
## How plugins work
write: function (pluginName, name, write) { ... },
            load: function (name, parentRequire, load, config) {
              // Require the intended dependency
              parentRequire([name], function (val) {
                // Add extra functionality
                val.extra = function () { alert('extra!'); };
                // resolve the dependency manually
                load(val);
              });
            }
            
require(['plugin!module'], function (module) {
              module.extra(); // alerts 'extra!'
            });
            
We can signficantly *reduce boilerplate* by using this simple feature.
# Getting Rid of MVWTF *Boilerplate*
One of the goals of ES Harmony is to reduce *setup boilerplate*. We should have the same goals in our modules.
## A simple example What can we get rid of?
define('view/main', [
            'backbone', 'handlebars', 'text!tmpl/one', 'h/myHelper'
            ], function (Backbone, Handlebars, oneTxt, myHelper) {
              Handlebars.registerHelper('myHelper', myHelper);
              return Backbone.view.extend({
                initialize : function () {
                  this.template = Handlebars.compile(oneTxt);
                }
              });
            });
            
## A simple example First let's make it an anonymous module
define([
            'backbone', 'handlebars', 'text!tmpl/one', 'h/myHelper'
            ], function (Backbone, Handlebars, oneTxt, myHelper) {
              Handlebars.registerHelper('myHelper', myHelper);
              return Backbone.view.extend({
                initialize : function () {
                  this.template = Handlebars.compile(oneTxt);
                }
              });
            });
            
## A simple example Then let's require it via a *view!* plugin
define([
              'handlebars', 'text!tmpl/one', 'h/myHelper'
            ], function (Handlebars, oneTxt, myHelper) {
              Handlebars.registerHelper('myHelper', myHelper);
              return {
                initialize : function () {
                  this.template = Handlebars.compile(oneTxt);
                }
              };
            });
            // use via: require('view!main');
            // the view! plugin could automatically start in the
            // `view` folder for you
            
The *view!* plugin would simply return the module wrapped as a Backbone.extended object
## A simple example Then let's turn template compilation into a plugin too
define(['handlebars', 'hbs!tmpl/one', 'h/myHelper'],
            function (Handlebars, one, myHelper) {
              Handlebars.registerHelper('myHelper', myHelper);
              return {
                initialize : function () {
                  this.template = one;
                }
              };
            });
            

The *hbs!* plugin can just return templates as a function.
## A simple example Then let's resolve the template's dependencies automatically
define(['hbs!tmpl/one'], function (one) {
              return {
                initialize : function () {
                  this.template = one;
                }
              };
            });
            

With handlebars, I can just introspect a template's AST to figure out it's dependencies.
## A simple example *Ultimately* you could create a convention to always have a template with the same name as a view
define({
                initialize : function () {}
            });
            

This one is a bit extreme, as most apps can't follow that convention rigidly. And because a real world example would have other dependencies anyways. But it has a nice effect.
## A simple example
*And since I'm being contrived*
define({});
              

Backbone doesn't require you to define an *initialize* function.
# Builds and performance
## Plugins as a vehicle for build time ## *static compilation*
There's so much that your app *doesn't* need to do at runtime in production.
## Consider Templates
require(['handlebars', 'text!tmpl'],
          function (Handlebars, tmpl) {
            alert( Handlebars.compile( tmpl )({ data: 1 }) );
          });
          

This includes the parser and the compiler for Handlebars, and must re-run those (slowest) parts on each render.
How many of you are *precompiling* templates at all?
## Auto precompilation We can make our modules do _all_ the work here.
load: function (name, parentRequire, load, config) {
              load.asText('hbs!'+name,
                'define(["handlebars"], function (H){ '+
                 'return H.template(H.precompile(' + tmplTxt +
                ')); })');

              parentRequire(['hbs!'+name], function (val) {
                load(val);
              });
            }
            
At runtime before build, the plugin is *eval'd*.
At build-time, it is written directly as the module.
## We now have a *transparent* way of ##   * Pulling in a template * Compiling it * Resolving all of its dependencies * Precompiling it at build time * Adding in introspection and buildtime optimizations (dead code removal)
## we can go *deeper*
## Templates can declare *style* dependencies and we can build up only the styles that are _used_.
## We can introspect CSS and *inline images* as data-uris at build time.
## We can inline the entire CSS block (including data-uris) and inject it with a *<style>* tag.
## We can bring our entire app down to a ## *single request*
## Static precompiliation is *so cool*
## Dead Code Removal Use in tandem with *has.js* to enable dead code removal.
if (has('val') ) {
               doSomething();
            }
            // changes to
            if (false) {
              doSomething();
            }
            

Uglify will remove dead code blocks like this
## Transparently precompile everything ##   * templates * i18n * i18n in templates * configurable apps. multi-profile apps. * coffeescript * less.js
## Build Profiles
require(['profile!module'], function (mod) {
              // mod is different depending on the profile setting.
            });
            

This can be *hugely* helpful when doing specialized builds for *IE* or *Mobile Devices*.
Consider simply a jQuery/zepto profile.
See [jensarps/AMD-feature](https://github.com/jensarps/AMD-feature)
The goal is to have a nice dev experience, but at build time, send absolutely *only* the code that is *necessary* and *precompute everything* possible.
  • Happiness
  • Speed
  • Modularity
  • Magic
# The *End* ##   * Alex Sexton * AlexSexton [at] gmail * [alexsexton.com](http://alexsexton.com) * [@slexaxton](http://twitter.com/slexaxton) * [github.com/slexaton](https://github.com/slexaxton)