0
votes

I am using BrunchJS to handle coffee script and assets compilation. The project uses several Brunch plugins such as brunch-handlebar which requires the "commonjs" wrapper to operate.

Extract from my config.coffee

    modules:
        # We cant avoid require js wrapping since brunch modules use commonjs
        # Otherwise Marionnette JS offers its own modules loading strategy
        # loading mechanism
        wrapper: "commonjs"
        definition: "commonjs"

On the Marionette side I can have a simple application loading just fine.

index.html

  <script type="text/javascript">
    var app = require('application');
    app.initialize()
  </script>

application.coffee

# Load handlebars block helpers require 'lib/view_helper'

class Application extends Backbone.Marionette.Application
    initialize: =>

        @addInitializer((options) =>
            console.log "HELLO WORLD"
            AppLayout = require 'views/app_layout'
            @layout = new AppLayout()
            @layout.render()                
        )

        @start()

# module.exports is the object that's actually returned as the result of 
# a require call.
module.exports = new Application()

Starting from there how do I use Marionette JS modules ? I read about using modules with AMD here https://github.com/marionettejs/backbone.marionette/wiki/AMD-Modules-vs-Marionette's-Modules but I can not use the define keyword in my marionette module definition since "define" and "require" are not exposed. Brunch only uses it to load its plugins and my app source files.

A usual Marionette module looks like this:

MyApp = new Backbone.Marionette.Application();

MyApp.module("Foo", function(){

  // module code goes here

});

MyApp.start();

In a separate file moduleA.coffee I tried to do:

MyApp = require 'application'

define ["MyApp", "Marionette"], (MyApp, Marionette) ->
  MyModule = MyApp.module("MyModule")

  MyModule.addInitializer ->
    console.log "HELLO FROM MODULE"

  MyModule

But define is not defined.

I also tried to do:

MyApp = require 'application'

MyApp.module "ModuleA", (MyApp, ModuleA, Backbone, Marionette, $, _)  ->
    ModuleA.addInitializer ->
        console.log "HELLO FROM MODULE"

but then I need to require all my marionette modules ("moduleA") in application.coffee and ran into some circular dependency issues.

One of the solution I am thinking about is to disable BrunchJS commonjs wrapping and load handlebars from vendor folder instead of as a brunch plugin.

1
Have you set up you require.config? I'm not sure about coffeeScript but I can give you a js example.Jonathan Miles
No I did not since I believe Brunch does it for us? I will give it a try.coulix
It's possible it does, I'm not sure about Brunch either. I use require, backbone marionette a lot and do not have this issue... so probably worth checking.Jonathan Miles

1 Answers

1
votes

JavaScript example in case it helps!

I think the important bit is initiating you bootstrapper (main.js, in this example) via require. It should be provided in a script tag attribute called 'data-main'. Perhaps this is something Brunch does for you, I'm not sure.

<script type="text/javascript" data-main="js/main" src="js/libs/require.js')}"></script>

Then your main.js might look something like this.

/* global require, console */
require.config({

    baseUrl: 'js',

    paths: {
        'jquery': 'libs/jquery/jquery',
        'underscore': 'libs/underscore/underscore',
        'backbone': 'libs/backbone/backbone',
        'backbone.wreqr': 'libs/backbone.wreqr/lib/backbone.wreqr',
        'backbone.babysitter': 'libs/backbone.babysitter/lib/backbone.babysitter',
        'marionette': 'libs/marionette/lib/core/backbone.marionette'
        ...
    },

    shim: {
        'underscore':  {
            deps: ['jquery'],
            exports: '_'
        },
        'backbone': {
            deps: ['underscore', 'jquery'],
            exports: 'Backbone'
        },
        'backbone.wreqr': {
            deps: ['backbone', 'underscore'],
            exports: 'wreqr'
        },
        'backbone.babysitter': {
            deps: ['backbone', 'underscore'],
            exports: 'babysitter'
        },
        'marionette': {
            deps: ['backbone', 'backbone.wreqr', 'backbone.babysitter'],
            exports: 'Marionette'
        }
    }
});

// Start the main app logic.
require([
    'app'
],
function (App) {
    App.start();
});

Once this is all setup, you can initiate any resource prefixing the function with define, like this...

define([
    'jquery',
    'underscore',
    'backbone',
    'marionette'
],
function ($, _, Backbone, Marionette) {
    'use strict';

    // code goes here
});