Configure a generic jQuery plugin with Browserify-shim?

前端 未结 4 583
南笙
南笙 2020-12-07 12:40

I\'m using browserify-shim and I want to use a generic jQuery plugin. I have looked over the Browserify-shim docs multiple times and I just can\'t seem to understand what\'s

4条回答
  •  一整个雨季
    2020-12-07 13:28

    Just for completeness, here is a method that exploits jQuery's CommonJS awareness to avoid having to worry about polluting the window object without actually needing to shim.

    Features

    1. jQuery included in the bundle
    2. plugin included in the bundle
    3. no pollution of the window object

    Config

    In ./package.json, add a browser node to create aliases for the resource locations. This is purely for convenience, there is no need to actually shim anything because there is no communications between the module and the global space (script tags).

    {
      "main": "app.cb.js",
      "scripts": {
        "build": "browserify ./app.cb.js > ./app.cb.bundle.js"
      },
      "browser": {
        "jquery": "./node_modules/jquery/dist/jquery.js",
        "expose": "./js/jquery.expose.js",
        "app": "./app.cb.js"
      },
      "author": "cool.blue",
      "license": "MIT",
      "dependencies": {
        "jquery": "^3.1.0"
      },
      "devDependencies": {
        "browserify": "^13.0.1",
        "browserify-shim": "^3.8.12"
      }
    }
    

    Method

    • Because jQuery is CommonJS-aware these days, it will sense the presence of the module object provided by browserify and return an instance, without adding it to the window object.
    • In the app, require jquery and add it to the module.exports object (along with any other context that needs to be shared).
    • Add a single line at the start of the plugin to require the app to access the jQuery instance it created.
    • In the app, copy the jQuery instance to $ and use jQuery with the plugin.
    • Browserify the app, with default options, and drop the resulting bundle into a script tag in your HTML.

    Code

    app.cb.js

    var $ = module.exports.jQuery = require("jquery");
    require('expose');
    
    $(document).ready(function() {
    
        $('body').append(
            $('')
                .css({"position": "relative",
                      "top": "100px", "left": "100px"})
                .click(function() {
                    $(this).expose();
                })
        );
    });
    

    at the top of the plugin

    var jQuery = require("app").jQuery;
    

    in the HTML

    
    

    Background

    The pattern used by jQuery is to call it's factory with a noGlobal flag if it senses a CommonJS environment. It will not add an instance to the window object and will return an instance as always.

    The CommonJS context is created by browserify by default. Below is an simplified extract from the bundle showing the jQuery module structure. I removed the code dealing with isomorphic handling of the window object for the sake of clarity.

    3: [function(require, module, exports) {
    
        ( function( global, factory ) {
    
            "use strict";
    
            if ( typeof module === "object" && typeof module.exports === "object" ) {
                module.exports = factory( global, true );
            } else {
                factory( global );
            }
    
        // Pass this if window is not defined yet
        } )( window, function( window, noGlobal ) {
    
        // ...
    
        if ( !noGlobal ) {
            window.jQuery = window.$ = jQuery;
        }
    
        return jQuery;
        }) );
    }, {}]
    

    The best method I found is to get things working in the node module system and then it will work every time after browserify-ing.
    Just use jsdom to shim the window object so that the code is isomorphic. Then, just focus on getting it to work in node. Then, shim any traffic between the module and global space and finally browserify it and it will just work in the browser.

提交回复
热议问题