Search code examples
javascriptjquerygulpbrowserify

How to manage dependencies with browserify when not using components?


I am using gulp with browserify to pull all my js dependencies into one file, then minify the file for production. The problem is that the order in which I am requiring my modules is not the order in which they are output.

As a simplified example, I have a script.js file that basically goes:

var $         = require('jquery');
var gsap      = require('gsap');
var hi        = require('hoverintent'); 

$('#someID').hoverIntent(function(){
    //do something
},function(){
    //do something
}

but I get the error "hoverIntent is not a function".

I look at the output file and see that browserify is writing the hoverIntent plugin before jQuery which is a dependency even though I require jQuery first.

Is this normal behavior"? If it is what is the best practice for dependency management is this sort of case? My limited experience with browserify in the past has been with reactjs, and in that case I required dependencies for each component which worked fine. What is best practice for a site / app that does not use components?


Solution

  • Your problem is you are relying on the side effect of the hoverIntent plugin adding it's function to jQuery. That is why jQuery plugins/extensions are a smell but let's ignore that.

    You should have one module that requires jQuery, adds your hoverIntent function to jQuery and then exports the jQuery that now has the function on it. Then everything should use that module instead of requiring jQuery directly.

    The normal CommonJS pattern is:

    1. Have some behavior - wrap it in a module.
    2. When you need that behavior, require the module and use it with the variable name you required it to.

    Note how #2 is being violated in your code above -- you require hoverintent as hi but do not use it as such. So by putting that issue down in your custom jQuery (which is jQuery plus hoverintent), you push that annoying pattern violation off to one module instead of repeat it across the code base.

    You can of course augment jQuery when you look the plugin. The other reply includes the example and I'll put it right here:

    var $ = require('jquery');
    require('hoverintent-jqplugin')($);
    

    My viewpoint is you now mutated jQuery and it would be best to put that mutation in one place. That is why I suggest pushing it down to one module. By mutate, I mean when another module requires jQuery after this module, it will have .hoverIntent but if it is requiring jQuery before, it won't. If the rest of your team doesn't understand this 100%, things can get messy (and if they do understand it, it is still messy).