Подтвердить что ты не робот

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

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


<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-запрос - я ожидал, что библиотека закрытия создаст тэг script для извлечения bar.js.

помощь!;)

4b9b3361

Ответ 1

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

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

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

Для разработки вы должны использовать (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 файлу относительно закрытия-библиотеки/закрытия/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>

Примечание:

  • В дополнение к включению базы base.js, я включаю в себя мои сгенерированные deps.js
  • Как упоминалось в учебнике вызов goog.require должен быть в отдельном теге script, поскольку он добавляет script тег для загрузки необходимых скриптов, и они загружаются после завершения текущей тега script.

Gotchas:

Ответ 2

Обновление!!!

Новая версия 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 на окнах, так что это тоже куча удовольствия. Несколько хаков заставили его работать для меня (что я не стану здесь, так как я не программист на питоне, и там должны быть лучшие способы сделать это).

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

Гвидо

Ответ 3

Мне удалось заставить его работать, добавив следующее к 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.

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

Ответ 5

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

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

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

Ответ 6

В любом случае, чтобы заставить пользовательские модули работать, по крайней мере, для версии разработки, включить вручную файлы 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, чтобы получить все преимущества библиотеки закрытия.

Ответ 7

решение:

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

  • не утруждайтесь настройкой загрузки, задержки, воспроизведения с помощью async и т.д.

  • они не будут работать (они также очень плохой дизайн и очень хромой.)

- это ваш 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);
  • ваш callback "просто активирует стартер, когда файл выполнил рендеринг,

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

p.s.

  • Синтаксис окна ['....'] заключается в том, что вы можете безопасно использовать short-compiler для max и всегда использовать одно и то же имя (хотя есть и другие способы сделать это, но это простое "всегда работающее" "путь..).

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

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

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

но, как правило, современные браузеры действуют лучше, когда вы обертываете их "неважно, просто делайте это в конце, например, JSONProtocol callback" stuff -

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

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