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?
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).
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.
window
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"
}
}
module
fourni par browserify et renverra une instance sans l'ajouter à l'objet window
.require
jquery et ajoutez-le à l'objet module.exports
(ainsi que tout autre contexte devant être partagé).$
et utilisez jQuery avec le plug-in.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>
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.
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.