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:
Stop development and re-tab everything. This sucks because development is stopped until files are tabbed and the code actually works with RJS.
Use CommonJS pattern, and use RJS CommonJS converter pre-RJS optimize. Seems hacky.
- 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.