web-dev-qa-db-fra.com

Configurer un plugin jQuery générique avec Browserify-shim?

J'utilise browserify-shim et je veux utiliser un plugin générique jQuery. J'ai consulté la documentation de Browserify-shim plusieurs fois et je n'arrive pas à comprendre ce qui se passe et/ou comment il sait où placer les plugins, les joindre à l'objet jQuery, etc. :

"browser": {
  "jquery": "./src/js/vendor/jquery.js",
  "caret": "./src/js/vendor/jquery.caret.js"
},

"browserify-shim": {
  "caret": {
     "depends": ["jquery:$"]
  }
}

Selon l'exemple donné dans la documentation de browserify-shim, je ne souhaite pas spécifier d'exportations, car ce plugin (et la plupart sinon tous les plugins jQuery) s'attache à l'objet jQuery. À moins que je ne fasse quelque chose de mal ci-dessus, je ne comprends pas pourquoi cela ne fonctionne pas (une erreur me dit que la fonction est indéfinie) lorsque je l'utilise. Voir ci-dessous:

$('#contenteditable').caret(5);  // Uncaught TypeError: undefined is not a function

Ma question est donc la suivante: comment configurer un plugin générique jQuery (qui s’attache à l’objet jQuery) avec browserify et browserify-shim?

40
Glen Selle

Pour tous ceux qui recherchent un exemple concret:

Voici un exemple de fichiers package.json et app.js pour un plug-in jQuery qui s'attache à l'objet jQuery/$, par exemple: $('div').expose(). Je ne veux pas que jQuery soit une variable globale (window.jQuery) lorsque j'en ai besoin, c'est pourquoi jQuery a la valeur 'exports': null. Cependant, comme le plug-in attend un objet global jQuery auquel il peut s'attacher, vous devez le spécifier dans la dépendance, après le nom de fichier: ./jquery-2.1.3.js:jQuery. En outre, vous devez exporter la variable jQuery global lorsque vous utilisez le plug-in, même si vous ne le souhaitez pas, car le plug-in ne fonctionnera pas autrement (du moins celui-ci).

package.json

{
  "name": "test",
  "version": "0.1.0",
  "description": "test",
  "browserify-shim": {
    "./jquery-2.1.3.js": { "exports": null },
    "./jquery.expose.js": { "exports": "jQuery", "depends": [ "./jquery-2.1.3.js:jQuery" ] }
  },
  "browserify": {
    "transform": [
      "browserify-shim"
    ]
  }
}

app.js

// copy and delete any previously defined jQuery objects
if (window.jQuery) {
  window.original_jQuery = window.jQuery;
  delete window.jQuery;

  if (typeof window.$.fn.jquery === 'string') {
    window.original_$ = window.$;
    delete window.$;
  }
}

// exposes the jQuery global
require('./jquery.expose.js');
// copy it to another variable of my choosing and delete the global one
var my_jQuery = jQuery;
delete window.jQuery;

// re-setting the original jQuery object (if any)
if (window.original_jQuery) { window.jQuery = window.original_jQuery; delete window.original_jQuery; }
if (window.original_$) { window.$ = window.original_$; delete window.original_$; }

my_jQuery(document).ready(function() {
  my_jQuery('button').click(function(){
    my_jQuery(this).expose();
  });
});

Dans l'exemple ci-dessus, je ne voulais pas que mon code définisse des globales, mais je devais le faire temporairement pour que le plugin fonctionne. Si vous n'avez besoin que de jQuery, vous pouvez le faire sans aucune solution de contournement: var my_jQuery = require('./jquery-2.1.3.js'). Si vous voulez que votre jQuery soit exposé en tant que global, vous pouvez modifier l'exemple package.json ci-dessus comme suit:

  "browserify-shim": {
    "./jquery-2.1.3.js": { "exports": "$" },
    "./jquery.expose.js": { "exports": null, "depends": [ "./jquery-2.1.3.js" ] }

J'espère que cela aide certaines personnes qui recherchaient des exemples concrets (comme moi, quand j'ai trouvé cette question).

12
gottlike

Juste pour compléter, voici une méthode qui exploite la conscience de CommonJS de jQuery pour éviter de s’inquiéter de la pollution de l’objet window sans avoir réellement besoin de shim.

Caractéristiques

  1. jQuery inclus dans le forfait
  2. plugin inclus dans le bundle
  3. pas de pollution de l'objet window

Config

Dans ./package.json, ajoutez un nœud browser pour créer des alias pour les emplacements de ressources. Ceci est purement pratique, il n’est pas nécessaire de calmer quoi que ce soit car il n’ya pas de communication entre le module et l’espace global (balises script) .

{
  "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"
  }
}

Méthode

  • Comme jQuery est conscient de CommonJS, il détectera la présence de l'objet module fourni par browserify et renverra une instance sans l'ajouter à l'objet window.
  • Dans l'application, require jquery et ajoutez-le à l'objet module.exports (ainsi que tout autre contexte devant être partagé).
  • Ajoutez une seule ligne au début du plug-in pour obliger l'application à accéder à l'instance jQuery créée.
  • Dans l'application, copiez l'instance de jQuery dans $ et utilisez jQuery avec le plug-in.
  • Browserify l'application, avec les options par défaut, et déposez l'ensemble résultant dans une balise de script dans votre code HTML.

Code

app.cb.js

var $ = module.exports.jQuery = require("jquery");
require('expose');

$(document).ready(function() {

    $('body').append(
        $('<button name="button" >Click me</button>')
            .css({"position": "relative",
                  "top": "100px", "left": "100px"})
            .click(function() {
                $(this).expose();
            })
    );
});

en haut du plugin

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

dans le HTML

<script type="text/javascript" src="app.cb.bundle.js"></script>

Contexte

Le modèle utilisé par jQuery est d'appeler son usine avec un indicateur noGlobal s'il détecte un environnement CommonJS. Cela n'ajoutera pas d'instance à l'objet window et renverra une instance comme toujours.

Le contexte CommonJS est créé par browserify par défaut. Vous trouverez ci-dessous un extrait simplifié du paquet illustrant la structure du module jQuery. J'ai supprimé le code traitant de la gestion isomorphe de l'objet window par souci de clarté. 

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;
    }) );
}, {}]

La meilleure méthode que j'ai trouvée consiste à mettre les choses en place dans le système de modules de noeuds, puis cela fonctionnera à chaque fois après la navigation.
Utilisez simplement jsdom pour caler l’objet window afin que le code soit isomorphe. Ensuite, concentrez-vous sur son fonctionnement dans le noeud. Ensuite, supprimez tout trafic entre le module et l’espace global et, enfin, naviguez-le et le tout fonctionnera dans le navigateur.

1
Cool Blue

J'utilisais wordpress. Par conséquent, j'ai été un peu forcé d'utiliser le jQuery du noyau wordpress, disponible dans l'objet window.

Il générait une erreur slick() non définie lorsque j'ai essayé d'utiliser le plugin slick() à partir de npm. Ajouter browserify-shim n'a pas beaucoup aidé.

J'ai fait des recherches et découvert que require('jquery') n'était pas toujours cohérent.

Dans mon fichier javascript de thème, il appelait jquery du noyau wordpress.

Mais, dans slick jquery plugin, il appelait la dernière version de jquery à partir de modules de noeud.

Finalement, j'ai pu le résoudre. Donc, partage de la configuration package.json et gulpfile.

package.json:

"browserify": { "transform": [ "browserify-shim" ] }, "browserify-shim": { "jquery": "global:jQuery" },

gulpfile.babel.js:

browserify({entries: 'main.js', extensions: ['js'], debug: true}) .transform(babelify.configure({ presets: ["es2015"] })) .transform('browserify-shim', {global: true})

Faire la transformation 'browserify-shim' était une partie cruciale, je manquais plus tôt. Sans cela, browserify-shim n'était pas cohérent.

0
Jashwant