How do I manage relative path aliasing in multiple grunt-browserify bundles?

browserify, gruntjs

Solution

These answers depend on how the rest of your project is setup, but maybe it's a good starting point. Also, you will need to use current v2 beta of grunt-browserify for this to actually work (`npm install grunt-browserify@2`).

1.

You can use aliasMapping to create some dynamic aliases for your modules. Just for clarity, lets move all your modules to `src/modules/`. Then, aliasMapping configuration could be something like this:

options: {
  aliasMappings: {
    cwd: 'src',
    src: ['modules/**/*.js']
  }
}

Lets suppose you have a module in `src/modules/magic/stuff.js`, then you can require it like this, regardless of where the .js file that's doing the require is located:

var magicStuff = require('modules/magic/stuff.js');

2.

Not sure about this one. Your project structure shows a `spec/index.js`, but you mention `spec/specs.js`. Are they supposed to be the same file?

Anyways, what duplicate work are you talking about? Because `./index.js` has a different entry file than `spec/index.js`. If you are looking for a way to include `./index.js` in `specs/`, then maybe you can copy it before running the tests instead of building it from scratch.

Problem

This is tad long but I'll need the code example to illustrate my confusion. After which I am interested to the answer for the following: - How do I use `require('module')` instead of `require('../../src/module')` or `require('./module')`? - How do I reuse `./index.js` in `spec/specs.js` without duplicating work? (And preventing `src/app.js` from running as it's an entry module). I've started several browser based projects already and love browserify and grunt. But each project dies at the same point in my development/learning curve. Once I add testing to the mix and have to manage two browserify bundles (`app.js` and `spec/specs.js`) the whole system falls apart. I'll explain: I use grunt-browserify and set my initial directory: ``` . ├── Gruntfile.js ├── index.js (generated via grunt-browserify) [1] ├── lib │   ├── jquery │   │   └── jquery.js [2] │   └── jquery-ui │   └── jquery-ui.js [3] ├── spec │   ├── specs.js (generated via grunt-browserify) [4] │   └── src │   ├── spec_helper.js (entry) │   └── module_spec.js (entry) └── src    ├── app.js (entry)    └── module.js ``` - Uses one entry file (`src/app.js`) and does a code walk to bundle all required modules. - Uses browserify-shim to alias `jquery`. - Is just aliased to `jquery-ui` without a shim (required after you `var $ = require('jquery')`). - Uses all helper and spec files in `spec/src` as entry modules. I'll step through my config: ``` browserify: { dist: { files: { 'index.js': ['src/app.js'] } } } // in app.js var MyModule = require('./module'); // <-- relative path required?! ``` Happy Now add jquery: ``` browserify: { options: { shim: { jquery: { path: 'lib/jquery/jquery.js', exports: '$' } }, noParse: ['lib/**/*.js'], alias: [ 'lib/jquery-ui/jquery-ui.js:jquery-ui' ] }, dist: { files: { 'index.js': ['src/app.js'] } } } // in app.js var $ = require('jquery'); require('jquery-ui'); var MyModule = require('./module'); ``` Happy Now add specs: ``` options: { shim: { jquery: { path: 'lib/jquery/jquery.js', exports: '$' } }, noParse: ['lib/**/*.js'], alias: [ 'lib/jquery-ui/jquery-ui.js:jquery-ui' ] }, dist: { files: { 'app.js': 'src/app.js' } }, spec: { files: { 'spec/specs.js': ['spec/src/**/*helper.js', 'spec/src/**/*spec.js'] } } // in app.js var $ = require('jquery'); require('jquery-ui'); var MyModule = require('./module'); // in spec/src/module_spec.js describe("MyModule", function() { var MyModule = require('../../src/module'); // <-- This looks like butt!!! }); ``` Sad To summarize: How do I... - Use `require('module')` instead of `require('../../src/module')` or `require('./module')`? - reuse `./index.js` in `spec/specs.js` without duplicating work? (And preventing `src/app.js` from running as it's an entry module).

Original source