SlexAxton/require-handlebars-plugin — pull request #113 by brettjonesdev (2013-05-25 02:06:11+00:00)
Title: Remove "hbs/" from hbs dependency declarations

##### The Problem: Unusual dependency definitions ("hbs/xxx" instead of "xxx")

I have been integrating hbs with a pre-existing Backbone/Marionette/Require project, and have run into issues that stem from the unusual way that `hbs.js` and `i18nprecompile.js` define their dependencies.

Note that in hbs.js, dependencies are declared like so:

```js
define(['Handlebars', 'hbs/underscore', 'hbs/i18nprecompile', 'hbs/json2']
```

And in i18nprecompile.js:
```js
define(['Handlebars', "hbs/underscore"], ...
```

Note the presence of `hbs\` in the path. This inclusion caused me significant headaches in my application. Here is the relevant part of my application's layout:

js
|-- app
| |-- config
| | |-- config.js
|-- libs
| |-- require.js
| |-- Handlebars.js
| |-- hbs.js
| |-- json2.js
| |-- i18nprecompile.js
| |-- underscore.js

`config.js` serves as my `data-main`. In its Require configuration, I use `baseUrl: 'js/app/'`, and library dependencies are aliased, like so: `hbs: "../libs/hbs"`.

This rather ordinary configuration and layout presents some issues because of the inclusion in `hbs.js` and `i18nprecompile.js` of the `hbs\` prefix on dependencies. First of all, I have a mapping for the top-level `hbs` plugin (`hbs: "../libs/hbs"` as noted before). RequireJS subsequently maps "hbs/underscore" to "../libs/hbs/underscore". This means that I would be forced to place underscore, json2 and i18nprecompile in a subdirectory, "js/libs/hbs". Since other parts of my app use underscore, moving it to an hbs-specific folder would be silly.

Essentially, this is forcing a directory structure upon my application. Anything which deviates from the layout in the demo app will fail without changing the source of hbs.js and i18nprecompile.js.

Interestingly, in `demo.html`, `paths` is defined like this:

```js
paths : {
'hbs' : '../hbs',
'Handlebars' : '../Handlebars',
'underscore' : '../hbs/underscore',
'i18nprecompile' : '../hbs/i18nprecompile',
'json2' : '../hbs/json2'
}
```

require.js is in the /demo folder, so /demo is effectively the `baseUrl`. An alias is defined for `hbs` - `"../hbs"`, which lets require find hbs in the root directory, above /demo. What is rather funny is that since `'hbs' : '../hbs'` is defined as an alias, when `hbs.js` and `i18nprecompile.js` are run, their stated dependencies of `"hbs/underscore"`, `"hbs/i18nprecompile"` and `"hbs/json2"` get evaluated like so:

1) "hbs" -> "../hbs" because of the alias in `paths`
2) "hbs/json2" -> "../hbs/json2", which works.

This is a very, very odd way of structuring things, and I suspect that many, many users trying to integrate hbs will be tripped up by this rather unusual layout behavior.

##### The Solution: Flat dependency definitions
A less brittle approach would be to define the dependencies in a flat manner, with a prepended `"hbs/"` in `hbs.js` and `i18nprecompile.js` like so:

###### hbs.js

```js
define(['Handlebars', 'underscore', 'i18nprecompile', 'json2']
```

###### i18nprecompile.js

```js
define(['Handlebars', "underscore"]
```

Then in the hypothetical application's RequireJS configuration, simply alias hbs's dependencies to their location, which can be anywhere we like: (in this case, /lib)

###### config.js
```js
paths: {
...
"underscore":"libs/underscore",
"i18nprecompile":"libs/i18nprecompile",
"json2":"libs/json2"
}
```

With this approach, hbs's 3 dependencies must be aliased in `paths` (or be located in the `baseUrl` directory, but that is probably not a good structure). This is technically more work than a hypothetical project which has the structure that hbs currently prescribes, but as I found, and indeed as the demo itself shows, you will probably need to do some aliasing in `paths` anyway, so in IMHO this is not even a drawback.

I have made the small changes I describe above in my own fork, and have confirmed that the demo works correctly, without any changes, in fact. I will be submitting a pull request shortly.