

Converting an existing Backbone.js project to Require.js - ozkatz
http://ozkatz.github.io/converting-an-existing-backbonejs-project-to-requirejs.html

======
CoffeeDregs
I'm really puzzled by the enthusiasm around RequireJS. I've read up on it,
I've built several large JS applications (~100 models, views, whatevers in
ExtJS and Knockout), have been involved with a large BackboneJS/RequireJS
application and am currently rebuilding a large site in AngularJS. AFAICT,
RequireJS did not solve any problems that I had more easily solved with proper
namespacing (yes, the feared __global __, e.g.
TheProject.controllers.chrome.SessionController) or that AngularJS doesn 't
solve more gracefully.

Instead, RequireJS yielded a fairly verbose and error-prone header* coupled
with large and distinct JS downloads for each and every page __. Add in
Backbone 's verbosity and it's boilerplate and hand-wiring all the way down.
Just the kind of thing for when you want to handcraft an artisan website, but
not so great for cranking out code.

* Good luck catching typos when you're pulling in 20 modules and you lose synchronization between the strings and the vars. Here's a __simple __example:
    
    
        define([
          'jquery',
          'handlebars',
          'backbone',
          'mymodel',
          'mycontrolleranimals',
          'mycontrollerpeople',
          'myview_cats',
          'myview_dogs',
          'myview_birds'
          ],
        function(
          $,
          Handlebars,
          Backbone,
          MyModel,
          MyControllerAnimals,
          MyControllerPeople,
          MyViewDogs,
          MyViewCats,
          MyViewBirds) {
    

Sure, you caught the error because you were looking for it, but what happens
in a RequireJS application is that you get weird errors in your application
because you were trying to use the MyViewDogs, but myview_cats was actually
bound to that variable.

 __To be perfectly honest, I didn 't build the system, so don't that it was
configured correctly.

~~~
ktt
Use this syntax, IMHO it's a LOT more readable:

    
    
       define(function(require) {
          var $ = require('jquery'),
              Handlebars = require('handlebars'),
              Backbone = require('backbone'),
              MyModel = require('mymodel'),
              MyControllerAnimals = require('mycontrolleranimals');
              

Also require.js comes with an optimizer that automatically concatenates all
required files (and no more!) minifies them and you don't have to worry about
script order. Also using the text plugin you can package templates (text
files) along with the rest of the scripts.

~~~
STRML
Wow, I've been using require.js for more than a year and I've never seen that
syntax used. `var module = require('module')` will only work if the module has
already been downloaded; otherwise, there's no way it can make an async call
and return the result.

What's interesting is that requireJS pulls a move very similar to Angular and
reads Function.prototype.toString() to pull those definitions back up into the
define() call, so it still works if an async call needs to be made. That's
really fantastic. As we've seen with Angular, there are some quirks (old
browsers, mainly), but code like this will be optimized out by r.js so there
will be no problems in production.

Thanks for the pointer, I may just change all of my definitions after seeing
this.

------
hippich
Minor nitpick which might simplify your life - instead of declaring
dependencies in the header (i.e. define(['xxx'],..)), just use any of your
dependencies with require('') inside your code. I.e. do something like this:

    
    
      define(function() {
        var $ = require("jquery");
      });
    

This will require one module per file and either define aliases inside
config.js or using full path to the modules, but will not push you to define
any dependencies upfront.

Also as a bonus, when you use r.js optimizer, which will concatenate your .js
file into one giant file, it automatically resolve dependencies and rewrite
header for you.

Also minor gotcha I had to deal with - since requirejs literally parse JS code
for any require("..") calls, you can not put module name into variable and do
require(variable_name) unless this code already loaded in the current context.
So try always put actual name into require("...") call.

disclaimer: working on quite large require.js powered app -
[https://www.myedu.com/](https://www.myedu.com/) \- not entire app is
converted into require.js, but you can already checkout My Jobs page to get an
idea of what is possible - e.g. async loading of various submodules when
needed depending on current route.

~~~
graue
Offtopic: your employer MyEdu constantly spammed me throughout college with
emails pretending to be from a university affiliate, when you had just slurped
everyone's email from the public contact database. The intent was clearly to
deceive and misrepresent the nature of the email. Shame on you for working for
a spammy and exploitative business.

~~~
hippich
I am sorry to hear that. Could you please email details to
pavel.karoukin@myedu.com so we could figure out what was going on and possible
make it right?

------
shtylman
Just use npm and browserify. Way simpler and you are already using npm
already. Let each module manage the dependencies it needs.

~~~
spion
Exactly. The benefits of having npm as a package manager really cannot be
overstated.

In my experience, requirejs has been nothing but one over-complicated under-
documented and inflexible mess

------
tristan_juricek
The RequireJS plugin system is really useful.

Alex Sexton's handlebars plugin is a great example of what sets this apart:
[https://github.com/SlexAxton/require-handlebars-
plugin](https://github.com/SlexAxton/require-handlebars-plugin)

\- The javaScript code only sees the compiled template function

\- Handlebars partials and helpers are automatically discovered and registered
as needed

\- The optimizer can be used to precompile all template code, makes for fast
page loads

I've been using this with an i18n solution that folds in the MessageFormat.js
project as well, which makes for a nice pluralization system even if you don't
need true localization.

------
possibilistic
Perhaps someone can clue me in, because I'm still at a loss for why there's so
much hype built around Require.js.

I develop JS primarily for the frontend, and I use Grunt, a global namespace,
and concat (or similar tooling) to piece things together.

Doesn't r.js execute dependency resolution code at run time? Can all
references to r.js be fully compiled out? Even a wrapper like Almond seems to
leave behind this kind of extra cruft. I don't want any dependency resolution
code in the production build, because that's a problem that needs to be solved
at compile time.

~~~
jafaku
I was thinking the same thing. Why would anyone want this?

~~~
codeonfire
Because it's more costly to maintain 10000 line javascript files, you can
start to reuse code at something smaller than the package level, you can have
better cohesion and less coupling.

The god-file approach to development leads to things like lots of search and
replace when something needs renamed, name collision, and duplicated utility
code everywhere.

~~~
jafaku
Wtf, who said anything about a 10k LoC js file?

"possibilistic" said dependency resolution must be done at compile time:

> I don't want any dependency resolution code in the production build, because
> that's a problem that needs to be solved at compile time.

~~~
codeonfire
The tool that is mentioned, grunt, appears to resolve dependencies at the
package level, not at the module/file level. Dependencies at the package level
with no module level resolution tend to cause very large source files because
no one is going to make a new package for each unit of code.

------
dmak
I thought Backbone and Require were 2 separate things?

~~~
sanderjd
They are. A better headline would have been something like "refactoring an
existing backbone.js project to use require.js". His project still uses
backbone.js, but now it also uses require.js.

------
denysonique
To Ruby on Rails users I recommend the requirejs-rails Gem -- it automatically
integrates RequireJS with the asset pipline. It can also server templates in
AMD compatible format instead of throwing them into the JST[] Array.

------
denysonique
One of the benefits of RequireJS is runtime script loading. You can configure
RequireJS to exclude some rarely used functionality/file from the minified
asset build -- The extra file will only be fetched when needed.

------
sandGorgon
Has anybody gotten Require.js to work with a CDN (say Cloudfront) and on IE
browsers (below IE9) ?

We had faced poor load time performance because of this.

~~~
_neil
If you aren't already, and depending on how big your app is, you may want to
compile your app into a single file using r.js. Keep in mind, you lose the
"load only what the current view needs" aspect of it. I've usually found it to
be a better loading experience when compiled.

------
soljin2000
Yeah or you could start with YUI and have real dependency management from the
start.

~~~
cwmma
yeah but then you'd be using yui

