Pergunta

I've created a jQuery UI widget which is dependent on some other custom JavaScript modules. I fetch these modules using requirejs during the "_create" method of the widget. This actually works great if, I have my end consumers define my "data-main" property. However, in the situation where my consumers are using requirejs on their own, and defining their own "data-main" property, this doesn't work.

Since I'm using requirejs to inject scripts via my widget from a totally different server, I run into a few problems with requirejs's normal way of dealing with this.

  • First, I can't use a package.json file unless I assume that all of my consumers have a package.json which contains the exact same resources as I have. On top of that, I've got DEV, TEST and PROD server URLs to deal with.
  • Second I can't use require.config to set my baseUrl during a load on their server, cause it may break everything that they are using require for.

The current implementation I have working requires the consumer to add a script reference to require with my data-main location (external server). Then add a script ref to my widget (external server). This works because nobody else at my company has ever even heard of requirejs :). The second I start showing them how to bundle all of their code into reusable JavaScript modules my solution is broken.

I want to come up with a solution whereas the end consumer can simply reference my single JavaScript widget, which in turn loads everything it needs to function.

Any suggestions on how to do this? I've thought about hacking my own version of require with a static data-main, then just assume they can have multiple requirejs libs. I WOULD HATE TO DO THAT...but I can't really think of a better way.

Foi útil?

Solução

Here is what I am going to do...

Couple of notes:

  • I'm using the jQuery UI widget factory pattern (but this isn't exactly a widget)
  • The widget code lives on a remote server and consumers only reference it, don't download it
  • I'm using requirejs to load widget dependencies
  • I want the greatest ease-of-use for the consuming developer

Since it's required that my jQuery UI widget be loaded ASAP so that the consumer has the context of the widget right away ( $(selector).mywidget ) I've decided to tackle my problem inside of the _create method.

This code basically installs requirejs if it doesn't exist, then uses it to install an array of requirements which the aforementioned widget needs to consume. This allows me to assume that the end user can reference my "widget" script by URL, tack on a "data-requiremodule" attribute of the same name, and get a complete list of remote dependencies.

 _create: function () {
   var widget = this;
   widget._establish(widget, function () {
     widget._install(widget);
   });
 },

 _getBaseURL: function (scriptId, callback) {
   var str = $('script[data-requiremodule="' + scriptId + '"]').attr('src');
   if (callback) callback(str.substring(str.search(/scripts/i), 0));
 },       

 _require: function (requirementAry, baseUrl, callback) {
   require.config({ baseUrl: baseUrl });
   require(requirementAry, function () {
     if (callback) callback();
   });
 },

 _establish: function (widget, callback) {
   if (typeof require === 'undefined') {
     widget._getBaseURL(widget._configurations.widgetName, function (baseUrl) {
       var requireUrl = baseUrl + 'scripts/require.min.js';
       baseUrl = baseUrl + 'scripts/';
       $.getScript(requireUrl, function (data, textStatus) {
         widget._require(widget._configurations.requiredLibs, baseUrl, function () { 
           callback(textStatus); 
         });
       });
     });
   }
 },

I'm not showing my "_configurations" object here...but you get the idea. I hope this helps someone else besides me :).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top