Как изолировать различные библиотеки javascript на одной странице?

Предположим, нам нужно встроить виджет на стороннюю страницу. Этот виджет может использовать jquery, например, так что виджет несет библиотеку jquery с собой. Предположим, что сторонняя страница также использует jquery, но другую версию. Как предотвратить конфликт между ними при встраивании виджетов? jquery.noConflict не является параметром, потому что для вызова этого метода для первой библиотеки jquery, загруженной на страницу, требуется этот метод, и это означает, что его следует называть сторонним сайтом. Идея заключается в том, что сторонний сайт не должен вносить изменения или делать что-либо в стороне, добавив тег с помощью src в виджет, чтобы использовать его.

Кроме того, это не проблема с jquery, в частности, в качестве примера может быть использована библиотека закрытия Google (даже скомпилированная).

Какие существуют решения для изоляции различных библиотек javascript, кроме очевидного iframe? Возможно, загрузка javascript в виде строки, а затем eval (с помощью функции ('code to eval'), а не eval ('code to eval')), это в анонимной функции может сделать трюк?

Ответы

Ответ 1

Function(...) делает eval внутри вашей функции, это не лучше.

Почему бы не использовать iframe, они предоставляют песочницу по умолчанию для стороннего контента.

И для дружественных вы можете обмениваться текстовыми данными между ними и вашей страницей, используя parent.postMessage для современного браузера или window.name для старых.

Ответ 2

На самом деле, я думаю, jQuery.noConflict - именно то, что вы хотите использовать. Если я правильно понимаю его , ваш код должен выглядеть следующим образом:

(function () {
var my$;

// your copy of the minified jQuery source

my$ = jQuery.noConflict(true);
// your widget code, which should use my$ instead of $
}());

Вызов noConflict приведет к восстановлению глобальных объектов jQuery и $ к их прежним значениям.

Ответ 3

Я создал библиотеку, чтобы решить эту проблему. Я не уверен, что это поможет вам, конечно, потому что код все же должен знать о проблеме и использовать библиотеку в первую очередь, поэтому она поможет только в том случае, если вы сможете изменить свой код для использования библиотеки.

Библиотека, о которой идет речь, называется Пакеты JS и может быть загружена и использована бесплатно, так как это Open Source в соответствии с лицензией Creative Commons.

В основном это работает с помощью кода упаковки внутри функций. Из этих функций вы экспортируете те объекты, которые хотите открыть для других пакетов. В потребительских пакетах вы импортируете эти объекты в локальное пространство имен. Неважно, если кто-то другой или даже вы сами используете одно и то же имя несколько раз, потому что можете устранить двусмысленность.

Вот пример:

(пример файла /greeting.js)

Package("example.greeting", function() {
  // Create a function hello...
  function hello() {
    return "Hello world!";
  };

  // ...then export it for use by other packages
  Export(hello);

  // You need to supply a name for anonymous functions...
  Export("goodbye", function() {
    return "Goodbye cruel world!";
  });
});

(пример файла /ambiguity.js)

Package("example.ambiguity", function() {
  // functions hello and goodbye are also in example.greeting, making it ambiguous which
  // one is intended when using the unqualified name.
  function hello() {
    return "Hello ambiguity!";
  };

  function goodbye() {
    return "Goodbye ambiguity!";
  };

  // export for use by other packages
  Export(hello);
  Export(goodbye);
});

(пример файла /ambiguitytest.js)

Package("example.ambiguitytest", ["example.ambiguity", "example.greeting"], function(hello, log) {
  // Which hello did we get? The one from example.ambiguity or from example.greeting?
  log().info(hello());  
  // We will get the first one found, so the one from example.ambiguity in this case.

  // Use fully qualified names to resolve any ambiguities.
  var goodbye1 = Import("example.greeting.goodbye");
  var goodbye2 = Import("example.ambiguity.goodbye");
  log().info(goodbye1());
  log().info(goodbye2());
});

example/ambiguitytest.js использует две библиотеки, которые экспортируют функцию "прощай", но могут явно импортировать правильные и назначать их локальным псевдонимам, чтобы их неоднозначность.

Использовать jQuery таким образом означало бы "упаковку" jQuery путем упаковки этого кода при вызове пакета и экспорта объектов, которые он теперь предоставляет в глобальную область. Это означает, что немного измените библиотеку, которая может быть не такой, какой вы хотите, но, увы, нет никакого способа обойти это, что я могу видеть, не прибегая к iframes.

Я планирую включить "упакованные" версии популярных библиотек в загрузку и jQuery, безусловно, включен в список, но на данный момент у меня есть только пакетная версия движка Sizzle, jQuery.

Ответ 4

Вместо поиска методов, подобных конфликту, вы вполне можете называть полный URL-адрес API Google для jQuery, чтобы он мог работать в приложении.

Ответ 5

<script src="myjquery.min.js"></script>
<script>window.myjQuery = window.jQuery.noConflict();</script>
...
<script src='...'></script> //another widget using an old versioned jquery
<script>
(function($){
    //...
    //now you can access your own jquery here, without conflict
})(window.myjQuery);
delete window.myjQuery;
</script>

Наиболее важные моменты:

  • вызов метода jQuery.noConflict() НЕМЕДЛЕННО ПОСЛЕ того, как ваши собственные jquery и связанные с ними теги плагинов

  • сохранить результат jquery в глобальную переменную с именем, которое имеет мало шансов конфликтовать или запутать

  • загрузите свой виджет с помощью старого jQuery с версией;

  • - это ваши логические коды. используя закрытие, чтобы получить частный $for convience. Частный $не будет конфликтовать с другими jquerys.

  • Вам лучше не забывать удалять глобальную переменную temp var.