Notes on using RequireJS with Backbone and/or Spine

2 minute read

For a project I’m currently working on I’ve decided to jump on the Javascript bandwagon with full weight. I intend to code in CoffeeScript, use either Spine or Backbone to give me a light-weight MVC architecture, and then deploy it all together in a clean, optimized way using RequireJS. If you’re not familiar with these tools and libraries then I recommend you follow the links to find out more about them. Basically, client-side Javascript-driven web app development is getting very exciting :)

I started off by getting Spine to to work with the RequireJS CoffeeScript adapter. In development mode everything worked fine but when I tested using the RequireJS-optimized output some of my Spine code didn’t seem to work. Here is my HTML file:

<!DOCTYPE html>
<html>
<head>
    <title>CoffeeScript Loader Plugin Demo</title>
    <script data-main="lib/main" src="lib/require-jquery.js"></script>
</head>
<body>
<p>
  <a class="test" href="#">Test</a>
</p>
</body>
</html>

The main.js script:

require({
    paths: {
        cs: '../../demo/lib/cs'
    }
}, ['spine','cs!csmain']);

And the csmain.coffee script:

define () ->
  Tasks = Spine.Controller.create
    tag: "body"

    events:
      "click .test" : "clicked"

    init: ->
      alert "loaded"

    clicked: (event) ->
      alert "clicked"

  Tasks.init
    el: document.body

I built on top of the RequreJS CoffeeScript demo files to save time.

On page load I should see an alert containing the text “loaded”. When I click the link I should get an alert containing the text “clicked”. In the RequireJS-optimized version (where all the scripts were compressed and inlined into main.js) I got the initial page load alert but no alert when I clicked on the link. Thinking that the use of coffeescript might have jinxed it I decided to code the Spine stuff in plain old Javascript instead, to no avail. I then replaced Spine with Backbone and coded the equivalent as such:

View = Backbone.View.extend
  el: $("body")

  events:
  "click .test" : "clicked"

  initialize: ->
  alert "loaded"

  clicked: ->
  alert "clicked"

new View()

CoffeeScript is beautiful, no!?

This failed in the same exact way that Spine did. So it wasn’t an issue with either of these libraries. Eventually, I took a chance and decided to not to use the combined RequireJS jQuery script and instead opted to include them separately. This is not the most recommended way of using RequireJS with jQuery, as is clearly stated in the RequireJS docs. Yet this combination worked for me - when I ran the optimized version I got the click-triggered alert box showing too. I can only guess that the RequireJS jQuery combo file breaks either jQuery or the assumptions Spine and Backbone make about jQuery.

So here is how I now initialize the scripts in the HTML:

<script>
require({
  baseUrl: 'lib',
  priority: ['jquery']
}, ['main']);
</script>

The RequireJS docs recommend additional configuration steps for the optimizer to work properly but I didn’t need to do that. My existing configuration worked fine:

({
    appDir: '.',
    baseUrl: 'lib',
    //Uncomment to turn off uglify minification.
    //optimize: 'none',
    dir: '../demo-build',
    paths: {
        cs: '../../demo/lib/cs'
    },
    // Exclude CoffeeScript compiler code
    pragmasOnSave: {
        excludeCoffeeScript: true
    },
    modules: [{
        name: "main"
    }]
})

Leave a Comment