d3.jsgruntjsbrowserifyyepnopedynamic-script-loading

using global for dependency with grunt-browserify


I'm using yepnope to load scripts conditionally, based on some tests, and I'm also using browserify, via grunt-browserify to build my scripts. Now I want one script to replace the other, but still be called via the same require:

// if svg support, then d3.js, otherwise r2d3.js
var d3 = require('d3');

So d3 is used as a require in my code, and also as a dependency for another lib.

The issue is that it can't be done with different require statements, because those are done during the build and the test can't happen because it depends on the users browser.

So I need a way to specify that the dependency uses d3 from window.d3, so I can set the window object with either of the libs. This is my grunt-browserify config..

options: {
  external: ['d3'],
  shim: {
    'd3-chart': {
       path: 'assets/bower_components/d3.chart/d3.chart.js',
       exports: null,
       depends: {
         d3: 'd3'
       }
    }
  }
}

I get Cannot find module 'd3' when r2d3 is loaded, even though that exports a window.d3.


Solution

  • With regards to Browserify, if you are using Browserify 3.0 you are able to utilize the browserify-shim as a transform, and expose a global reference to d3 by sticking a reference to D3 in your package.json like so:

     "browserify-shim": {
       "d3": "global:d3"
     }
    

    After installing the shim will need to add a transform for the browserify-shim if you have not already

    options: {
      transform: ['browserify-shim']
    }
    

    I wasn't able to confirm that this worked correctly in my build, as I discovered an alternate solution to my problem (I'm using xCharts). (Furthermore, I just switched to gulp.)