Как я могу загрузить свой собственный js-модуль с помощью goog.provide и goog.require?

Мы пытаемся переключить упаковку для нашего проекта с dojo на google closure, но пока нам не повезло. Вот простой пример, иллюстрирующий то, чего мы пытаемся достичь:


<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <script type="text/javascript" src="runtime/src/core/lib/goog-rev26/base.js"></script>
        <script>
            goog.require("foo.bar");
            function main() {foo.bar.echo("hello world")}
        </script>
    </head>
<body onload="main()">
</body>
</html>

Затем в /foo/bar.js у меня есть:


goog.provide("foo.bar");
foo.bar.echo = function(s) {console.debug(s);}

Ошибки, которые я получаю в firebug, следующие:

goog.require could not find: foo.bar
foo is not defined

Когда я смотрю на вкладку «Сеть», там нет http-запроса для извлечения файла — я ожидал, что библиотека закрытия сгенерирует тег сценария для извлечения bar.js.

помощь! ;)


person Lightbeard    schedule 17.12.2009    source источник


Ответы (7)


Я понял это, и это не очень сложно, но есть несколько ошибок.

По сути, вы можете использовать сценарий генерации зависимостей calcdeps.py (вы должны прочитать calcdeps.py документы) в одном из нескольких режимов:

  1. Создание файла deps.js
  2. Объединение всего в один файл, опциональная компиляция с помощью замыкающего компилятора.

Для разработки вы должны использовать (1), так как это позволяет вам не запускать calcdeps.py после редактирования исходников JS, если вы не внесете изменения в дерево зависимостей. Остальная часть ответа примерно такова, я еще не пробовал другой.

Вот что я сделал для его создания:

#!/bin/bash
cd closure-library/closure/goog
python ../bin/calcdeps.py -p ../../../js -o deps > ../../../my-deps.js

... предполагая следующую структуру каталогов:

project/
  closure-library/ (as checked out from SVN)
  js/ (my JS code)
  app.html

(параметр -p просматривает все файлы js в указанном каталоге, и в документах говорится, что вы можете указать несколько каталогов для поиска, если вам нужно.)

Приведенный выше вызов создает файл my-deps.js рядом с основным файлом app.html, который я использую для запуска приложения. Созданный файл содержит информацию о моих JS-файлах в js/ и выглядит так:

goog.addDependency('../../../js/controllers.js', ['proj.controllers'], []);
goog.addDependency('../../../js/ui.js', ['proj.ui'], ['proj.controllers']);

- где первая строка это путь к моему JS файлу относительно closure-library/closure/goog/base.js (это важно!), второй массив это список goog.provide-d строк , а последний массив — это список из goog.require-d строк.

Теперь в app.html у меня есть:

<script src="closure-library/closure/goog/base.js"></script>
<script src="my-deps.js"></script>
<script>
  goog.require("proj.ui");
</script>
<script>
  // here we can use the required objects
</script>

Примечание:

  1. Помимо включения base.js закрытия, я включаю сгенерированный deps.js
  2. Как упоминалось в руководстве, вызов goog.require должен находиться в отдельном теге скрипта< /a>, потому что он добавляет тег сценария для загрузки необходимых сценариев, и они загружаются после завершения обработки текущего тега сценария.

Гочки:

  1. Описанная выше проблема с путями относительно base.js. goog.require создает URL-адрес скрипта для загрузки путем объединения базового URL-адреса base.js (т. е. без имени листа base.js) и первого параметра goog.addDependency в deps.js.
  2. calcdeps.py плохо работает в Windows, в частности, с использованием обратная косая черта в строковых литералах deps.js
  3. Если что-то работает не так, вы можете просмотреть все проблемы, связанные с calcdeps, и убедитесь, что у вас есть актуальная проверка.
person Nickolay    schedule 05.01.2010

Обновлять!!!

Новая версия calcdeps.py немного меняет игру. Чтобы создать свой deps.js, теперь вам нужно использовать флаг -d. например:

python path-to-closure-library/closure/bin/calcdeps.py -i path-to-your-src/requirements.js -o deps -d path-to-closure-library/closure/ -p path-to-your-src/ --output_file=path-to-your-src/deps.js

Компилировать:

python path-to-closure-library/closure/bin/calcdeps.py -i path-to-your-src/requirements.js -d path-to-closure-library/closure/ -p ./ --output_file=path-to-your-release/scripts.min.js -c path-to-compiler/compiler.jar -f "--compilation_level=ADVANCED_OPTIMIZATIONS" -f "--debug=true" -f "--process_closure_primitives=true" -f "--manage_closure_dependencies=true" -o compiled

Таким образом, процесс на самом деле теперь намного проще, но вы должны использовать свои способности ESP, чтобы узнать об этом, поскольку он полностью не задокументирован. calcdeps.py теперь также не работает с Python 3.1 в Windows, так что это тоже очень весело. У меня это заработало с помощью нескольких хаков (которые я не буду приводить здесь, поскольку я не программист на Python, и должны быть лучшие способы сделать это).

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

Гвидо

person gatapia    schedule 14.07.2010

Мне удалось заставить его работать, добавив в deps.js следующее:
goog.addDependency('../../../foo/bar.js', ['foo.bar'], []);

Firefox теперь отправляет http-запрос к /foo/bar.js, когда встречает оператор goog.requires.

Однако файл содержит такой комментарий:
// This file has been auto-generated by GenJsDeps, please do not edit.

Согласно этому, GenJsDeps совпадает с calcdeps.py . Если вы посмотрите на документацию, похоже, что есть переключатель -o deps, который повторно генерирует deps.js, чтобы его не редактировали вручную.

person Lightbeard    schedule 17.12.2009
comment
Вы должны использовать calcdeps.py и не использовать addDepedency самостоятельно. - person Bjorn; 02.03.2010
comment
addDependency полезен, когда вы хотите развиваться. Компилятор Closure может занимать много времени на компиляцию. - person Andras Gyomrey; 22.06.2013

Да, вы должны использовать calcdepds.py. Я создал большой пост в блоге после долгих проб и ошибок, чтобы найти лучший способ сделать это, я также рассматриваю различия между dojo.require и goog.require:

http://apphacker.wordpress.com/2009/12/28/howto-how-to-use-goog-require-and-goog-provide-for-your-own-code/

person Bjorn    schedule 28.12.2009
comment
Да, я не продолжал платить за свой домен WordPress. Теперь это apphacker.wordpress.com/2009/12/28/, но calcdeps.py устарел. В репозитории библиотеки замыканий есть гораздо лучшие инструменты сборки, которые разбивают то, что раньше делал calcdeps. - person Bjorn; 26.05.2011

Вот небольшой проект, над которым я работал и который может быть вам полезен: http://github.com/fintler/lanyard

Взгляните на build.xml, файл с именем lanyard.js и все файлы, расположенные в src/geom/*.

В build.xml есть пример вызова calcdeps.py через ant для всех js, расположенных в src. Возможно, это не лучший способ сделать что-то, но до сих пор он работал для меня.

person Jon Bringhurst    schedule 23.02.2010

В любом случае, чтобы заставить работать пользовательские модули, по крайней мере, для версии для разработки, нужно вручную включить файлы js в раздел заголовка html-страницы после включения файла google base.js.

<script type="text/javascript" src="js/closure/goog/base.js"></script>
<script type="text/javascript" src="js/closure/custom/custom.js"></script>
<script type="text/javascript" src="js/closure/custom/sub/sub.js"></script>
...

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

person duganets    schedule 11.11.2010

решение:

  • загрузите закрытие на внешний вид вашего проекта (или активы, что угодно).

  • не беспокойтесь о настройке загрузки, задержки, игре с асинхронностью и т. д.

  • они не будут работать (они также являются очень плохим шаблоном проектирования и крайне хромыми..)

- это ваш main.js, где вы динамически внедряете свой код в DOM (например, создаете букмарклет или что-то в этом роде):

/**
 * loads the base.js of google closure.
 * http://code.google.com/p/closure-library/
 */

(function() {
  var s = document.createElement('script');
  s.type = "text/javascript";
  s.src = "./assets/closure/goog/base.js";
  s.async = true;
  document.getElementsByTagName("body")[0].appendChild(s);
}());

/**
 * activated from the base.js as JSONProtocol.
 */
window['starter'] = function() {
  console.log("hi...");
};

сейчас:

  • изменить свой base.js

добавить конец файла

......
.......
........

/**
 * run the method when done load. just like JSONProtocol.
 */
window.setTimeout(function() {
  window['starter']();
}, 5);
  • ваш "обратный вызов" просто активирует стартер, когда файл выполнил рендеринг,

  • он работает отлично и продолжает загружать каждый ресурс асинхронно.

p.s.

  1. синтаксис window['....'] таков, что вы можете безопасно использовать closure-compiler по максимуму и всегда использовать одно и то же имя (хотя есть и другие способы сделать это, но это простой «всегда работающий» способ. .).

2. на base.js вы также можете избежать тайм-аута и просто использовать

......
.......
........

/**
 * run the method when done load. just like JSONProtocol.
 */
window['starter']();

но, как правило, современные браузеры работают лучше, когда вы обертываете эти вещи «все равно, просто делайте это в конце, например, обратный вызов JSONProtocol» -

тайм-ауты (в основном используемые со значениями от 0 до 5) прерываются не как тайм-ауты, а как способ нарушить синхронность блока кода, что позволяет вести себя действительно как «переключение контекста».

хотя там есть дополнительные накладные расходы.

person Community    schedule 21.06.2013
comment
я действительно не понимаю, как это связано с загрузкой пакетов (например, сопоставление имени модуля с именем файла) - person Andras Gyomrey; 22.06.2013