2

I want to implement RequireJS in a very large single page application that uses CoffeeScript and Grunt. We have separate files for different modules (services, Backbone, etc.).

Implementing RequireJS is very straightforward - my main problem is with the size of the application and CoffeeScript's whitespace sensitivity. We need to be able to continuously develop new features while implementing RJS. The reason we cannot do this is because we would have to wrap all files in define calls, and re-tab files. When you try to rebase this code, massive merge conflicts arise due to the tabbing. No one has the time to solve all those problems, as new features and bugfixes may have been introduced pre-RJS.

I've research a few possible solutions:

  1. Stop development and re-tab everything. This sucks because development is stopped until files are tabbed and the code actually works with RJS.

  2. Use CommonJS pattern, and use RJS CommonJS converter pre-RJS optimize. Seems hacky.

  3. Use CoffeeScript backtick functionality to wrap CoffeeScript classes in a standard JavaScript module pattern. Next pass dependencies to the "module" wrapper for the CoffeeScript class then initialize the "module" within the RJS call in the file.

Edit: Thanks for the tip on the vertical structure & introducing me to passing function arguments that way (comma-less). Our projects are very similarly in structure (except grunt-contrib-coffeee does the linting, unfortunately, at the moment), and I am also building a custom watch task to compile single files (vs. glob patterns).

Consider this very basic example:

view.coffee:

class View
  template: Helper.template
  constructor: (@options) ->
  render: (meters) ->
    $('body').html @template @options

The normal process would be to do something like the following with RJS:

define [
  'jQuery'
  'Helper'
], (
  $
  Helper
) ->
  class View
    template: Helper.template 'base_view'
    constructor: (@options) ->
    render: (meters) ->
      $('body').html @template @options

Notice how the entire class has been re-tabbed. Git would hate this if any one of our developers came along and modified the View class, while I was trying to implement require in parallel.

The backtick idea won't work, I can't get around the global problem there:

`var exports = function($, Helper) {
class View
  template: Helper.template
  constructor: (@options) ->
  render: (meters) ->
    $('body').html @template @options
return View }(jQuery, Helper)`

define [
  'jQuery'
  'Helper'
], (
  $
  Helper
) ->
  return exports($, Helper)

I think my best bet is merging all of the applications features together and then pausing for a moment to re-tab every file the necessary two spaces, all in one commit. CoffeeScript doesn't seem to care where the indentation begins (column 0 vs column 2) as long as the rest of the file follows that pattern. We should be able to slide in RJS and implement it progressively in this way, preventing unsolvable merge conflicts.

rwoody
  • 36
  • 4

1 Answers1

0

What we do in our projects:

  • we use grunt-contrib-coffee and grunt-coffeelint to compile and validate coffee files. With this plugin, you can validate the coffeescript code while developing. You can use a json file which contains validation settings. This makes sure all developers use the same settings.

e.g:

{
  "no_tabs" : {
    "level" : "error"
  },

  "no_trailing_whitespace" : {
    "level" : "error"
  },

  "max_line_length" : {
    "value": 200,
    "level" : "error"
  },
  ...
  • minimize the chance of merge conflicts in requirejs dependecies by defining each dependency on a separate line.

e.g.

define [
 'dep1'
 'dep2'
 'dep3'
], (
  dep1
  dep2
  dep3
) -> 
  console.log "Hello"

instead of

define ['dep1', 'dep2','dep3'], (dep1, dep2, dep3) -> 
  console.log "Hello"
  • Only commit coffeescript files to source control. Generated javascript files (minified via grunt-contrib-requirejs) we don't commit (only when creating a production version).
  • we use a custom watch task to watch changed coffeescript files (among other files). Via growl the developer is notified when compilation or validation failed.
asgoth
  • 35,552
  • 12
  • 89
  • 98