Search code examples
jquerynode.jsgulpbrowserify

Call 'require("jquery")' only once


I'm using Gulp with Browserify.

I would like to call my scripts in a certain order: jQuery, jQuery-easing, Bootstrap, [other libs], then my own scripts.

This, obviously, does not work:

main.js

const $ = require("jquery");
require("bootstrap");
// require other libs
require("./scripts.js");

scripts.js

$(function () {
    // code that won't work
    // because $ is not defined
});

But if I do:

main.js

require("jquery");
require("bootstrap");
// require other libs
require("./scripts.js");

scripts.js

const $ = require("jquery");
$(function () {
    // code that will work
    // because $ is now defined
});

it works, but I wonder if it bundles my scripts well, and if it's a good thing to require jQuery 2 times…

Is there a better way to proceed?


Solution

  • This is actually the way Browserify (and other module bundlers such as Webpack, Rollup and Parcel) are designed to work! Each module should import all the other modules that it needs to run.

    The best way to understand why is to learn a little about how JavaScript module bundlers work.

    When Browserify parses your main.js file it recognises the require("...") function calls as the dependencies of that module. For example, main.js depends on jquery, bootstrap and ./scripts.js. It starts to build a graph in memory so that it knows which files link to which.

    ./main.js --> jquery
         |
         + -----> bootstrap
         |
         + -----> ./scripts.js
    

    Then it goes off and parses each of those dependencies and adds them to the graph.

    ./main.js --> jquery <----- +
         |                      |
         + -----> bootstrap     |
         |                      |
         + -----> ./scripts.js -+
    

    Each time it finds a new dependency it adds it to the graph and parses it to see which modules the dependency depends on.

    If one of your modules requires a module that has already been added to the graph (e.g. ./scripts.js depends on jquery) then the bundler doesn't need to add it to the graph again, it just creates another connection.

    Eventually it will have collected all of the modules that you've required and it can add each one to the bundle, before writing it to disk.

    It doesn't matter how many times you require jquery across your codebase, it will only be added to the dependency graph once, meaning it's fine to require it twice, because it won't change the size of the bundle.

    As your programs get bigger, so does the dependency graph and eventually you'll end up with complex module relationships like in the picture below.

    enter image description here