web-dev-qa-db-fra.com

supportant à la fois CommonJS et AMD

Existe-t-il un moyen de créer une micro-bibliothèque javascript (une bibliothèque sans dépendances), prenant en charge tous les formats de module suivants:

  • Définition de module asynchrone
  • CommonJS
  • exposer les exportations de la bibliothèque en tant qu'objet d'espace de noms global (pas de chargeur)
36
slobo

Voici une liste de divers formats de module compatibles entre eux .

Je suppose que celui que vous recherchez correspond à ce qu'ils appellent " commonjsStrict.js "

22
Lee

Oui, et je dois cette réponse à ded et à ses impressionnants modules:

(function(name, definition) {
    if (typeof module != 'undefined') module.exports = definition();
    else if (typeof define == 'function' && typeof define.AMD == 'object') define(definition);
    else this[name] = definition();
}('mod', function() {
    //This is the code you would normally have inside define() or add to module.exports
    return {
        sayHi: function(name) {
            console.log('Hi ' + name + '!');
        }
    };
}));

Ceci peut alors être utilisé:

  1. dans AMD (par exemple avec requireJS):

    requirejs(['mod'], function(mod) {
        mod.sayHi('Marc');
    });
    
  2. dans commonJS (par exemple, nodeJS):

    var mod = require('./mod');
    mod.sayHi('Marc');
    
  3. globalement (par exemple en HTML):

    <script src="mod.js"></script>
    <script>mod.sayHi('Marc');</script>
    

Cette méthode doit faire plus de publicité - si jQuery and co. commencé à l'utiliser, la vie serait beaucoup plus facile!

48
Marc

uRequire , Universal Module & Resource Converter est l'outil qui fait exactement cela. 

  • Il convertit principalement convertit AMD et CommonJS en UMD/AMD/CommonJS/script simple (aucun chargeur AMD requis)}.

  • Il permet l'exportation déclarative de modules, avec une noConflict() cuite au four.

  • Il peut manipuler des modules (injecter/remplacer/supprimer des dépendances OR code) au fur et à mesure de leur construction.

  • Il convertit coffeescript, coco, Livescript, icedCoffeescript et vous pouvez ajouter vos propres conversions dans un seul support!

7
Angelos Pikoulas

Juste pour mettre à jour un peu cette réponse en ce qui concerne @marc, je donne moi aussi le crédit de dédier et je l’ai mis à jour un peu pour tenir compte des dernières mises à jour:

(function (name, definition, context, dependencies) {
  if (typeof context['module'] !== 'undefined' && context['module']['exports']) { if (dependencies && context['require']) { for (var i = 0; i < dependencies.length; i++) context[dependencies[i]] = context['require'](dependencies[i]); } context['module']['exports'] = definition.apply(context); }
  else if (typeof context['define'] !== 'undefined' && context['define'] === 'function' && context['define']['AMD']) { define(name, (dependencies || []), definition); }
  else { context[name] = definition(); }
})('events', function () {
  // Insert code here
  return {
    sayHi: function(name) {
      console.log('Hi ' + name + '!');
    }
  };
}, (this || {}));

L'objet à la fin est une référence à l'étendue parent ou à l'étendue actuelle. Supposons que vous écrivez un paquet et qu'il ne s'agit que d'une partie du graphique, ce contexte peut être un objet à espacement de noms et il ne s'agit que tranche de cette tarte.

De plus, si vous souhaitez avoir des dépendances, il existe un paramètre facultatif à la fin de votre portée qui prend en charge un tableau. Dans ce cas, le paramètre definition peut alors utiliser chaque dépendance en tant qu'argument. En outre, les dépendances répertoriées dans un tableau seront nécessaires à l’intérieur de la plateforme node-js pour votre commodité.

Voir: https://Gist.github.com/Nijikokun/5192472 pour un exemple réel.

1
Nijikokun

J'ai résolu ce problème et réussi à supporter facilement:

  • Dojo AMD (référençant les spécifications RequireJS)
  • jQuery (sous $/jQuery.fn. [votre_bibliothèque_ici])
  • node.js utilisant Vanilla require ('path_to.js')
  • Fenêtre du navigateur. [Votre_bibliothèque_ici]

Il utilise une combinaison d'injection de dépendance et IIFE pour faire le travail.

Voir ci-dessous:

/*global jQuery:false, window:false */
// # A method of loading a basic library in AMD, Node.JS require(), jQuery and Javascript's plain old window namespace.
(function(exporterFunction) {
exporterFunction('cll',
    function(a,b) {
        return a+b;
    }
);
})(
    (function() { // Gets an exportFunction to normalize Node / Dojo / jQuery / window.*

        if ((typeof module != 'undefined') && (module.exports)) { // Node Module
            return function(library_name,what_was_exported) {
                module.exports = what_was_exported;
                return;
            };
        }
        if (typeof define != 'undefined' && define.hasOwnProperty('AMD') && define.AMD) { // Dojo AMD
            return function(library_name,what_was_exported) {
                define(function() {
                    return what_was_exported;
                });
            };
        }
        if (typeof jQuery === 'function') { // jQuery Plugin
            return function(library_name,source) {
                jQuery.fn[library_name] = source;
                return;
            };
        }
        if (typeof window != 'undefined') { // Fall down to attaching to window...
            return function(library_name,what_was_exported) {
                window[library_name] = what_was_exported;
            };
        }

    })(),
    (function() { 
        // ## Other Parameters Here
        // You could add parameters to the wrapping function, to include extra 
        // functionalilty which is dependant upon the environment... See 
        // https://github.com/forbesmyester/me_map_reduce for ideas.
        return 'this_could_be_more_arguments_to_the_main_function'; 
    })()
);

Public Gist disponible sur https://Gist.github.com/forbesmyester/5293746

0
Forbesmyester

Ceci est basé sur la réponse de Nijikokun. Puisque RequireJS déconseille l’utilisation de noms de modules explicites, cela a été omis dans cette version. Le deuxième argument du chargeur décrit les dépendances. Passez [] si vous n'avez pas besoin d'en charger.

var loader = function(name, dependencies, definition) {
  if (typeof module === 'object' && module && module.exports) {
      dependencies = dependencies.map(require);
      module.exports = definition.apply(context, dependencies);
  } else if (typeof require === 'function') {
    define(dependencies, definition);
  } else {
    window[name] = definition();
  }
};

loader('app', ['jquery', 'moment'], function($, moment) {
   // do your thing
   return something;
}
0
monken