#javascript #node.js #google-closure-compiler
#javascript #node.js #google-closure-compiler
Вопрос:
Я разрабатываю сетевое приложение между браузером и запущенным сервером node.js . Я делюсь большим количеством кода прямо сейчас, но когда я на самом деле разверну это, я бы хотел, чтобы клиент получал только код, специфичный для клиента. Мои варианты прямо сейчас:
1.) Реализовать любой browser/node.js различия при использовании наследования. Я пробовал это в нескольких местах, и в итоге у меня получилось множество классов, которые являются очень, очень простыми настройками своего родителя, часто лишь частично специализирующегося на одной функции. Мне не очень нравится этот стиль, потому что он означает много косвенных ссылок, когда вы пытаетесь выяснить, что на самом деле происходит.
2.) Определите константу типа IS_BROWSER в глобальной области видимости, а затем проверяйте ее всякий раз, когда мне нужно изменить пути кода в браузере против node.js . Затем closure скомпилирует все js с расширенной оптимизацией, чтобы удалить мертвый код в браузере (параметр IS_BROWSER = true). Есть ли какие-либо проблемы с этим подходом, предполагающим, что я делаю все, что мне нужно, чтобы получить расширенную оптимизацию в компиляторе закрытия?
3.) ?? Я открыт для предложений.
Комментарии:
1. Какую библиотеку JavaScript вы используете? Довольно много библиотек JavaScript устранят для вас различия между браузерами и node / rhino. Использование глобальной константы в соответствии с вашим # 2 также работает хорошо, но я считаю, что лучше всего использовать библиотеку, которая абстрагирует все это.
2. многие различия на самом деле являются отличиями в логике приложения, поэтому они не будут абстрагированы библиотекой.
3. Мне любопытно, какие логические различия будут в среде браузера по сравнению с серверной средой без головы? AFAIK, они оба поддерживают большинство одинаковых функций в среде. Если есть опасения по поводу использования процессора, потоков и т.д., То я думаю, что с помощью «has.js » библиотека для обнаружения функций среды может быть наиболее гибким способом в будущем.
4. @StephenChung: Не могли бы вы привести пример «библиотеки устранят различия между браузерами и node / rhino для вас»?
5. @bukzor, например, Dojo поддерживает большинство браузеров, rhino и node (хотя я не уверен, что поддержка node официально еще отсутствует).
Ответ №1:
Если вы используете расширенную компиляцию, любой неиспользуемый код должен быть удален; если вы правильно используете систему экспорта компилятора, любой серверный код, который не вызывается вашим клиентским кодом, не будет находиться в скомпилированной версии клиентского кода.
Вы могли бы записать весь свой код в один большой двоичный объект, а затем для вашего клиента добавить один файл с таким содержимым, как
goog.require('my.client.app');
goog.exportSymbol('my.app.entryPoint', my.client.app.entryPoint);
скомпилированный код не будет включать ничего, чего нет в дереве вызовов my.client.app.entryPoint
. Аналогично, если ваша компиляция экспортирует только точку входа на сервер, клиентский код будет исключен.
Приведенный выше стиль предназначен для написания вашего скрипта для предоставления некоторой функции, которая затем будет вызвана встроенным скриптом; чтобы объединить все это в один скрипт, вы могли бы сделать что-то намного проще:
goog.require('my.client.app');
my.client.app.entryPoint();
Чтобы убедиться, что вы не получаете много мертвого кода в выходных данных вашей компиляции, вы могли бы поиграть с чем-то вроде этого: ScriptCover
Комментарии:
1. Этот вопрос касается node.js и closure-compiler. Я не вижу никаких упоминаний о closure-library (cl), и cl не будет работать под node.js без помощи сторонних (четвертых?) Библиотек, Ни одна из которых в настоящее время не является качественной.
2. Хороший момент. Я написал пример кода в стиле библиотеки закрытия, но это совершенно необязательно.
3. Когда вы говорите «это не обязательно», это подразумевает, что есть другой способ. Есть ли?
4. Компилятор обрабатывает
goog.require
иgoog.exportSymbol
особым образом, но любой код, который вы добавите черезrequire
, может быть просто добавлен к тому, что вы хотите скомпилировать, иexportSymbol
может быть заменен наthis["varName"] = varValue
(this
надеюсь, по умолчанию для глобальной области или модуля) илиwindow["varName"] = varValue
for в браузере. Если вы получаете доступ к свойству по строке его имени, компилятор не переименует этот доступ. Чтобы гарантировать, что поле, к которому обращаются в . Стиль fieldName доступен с этим именем, вы должны использоватьexportSymbol
5. Тем не менее, я был бы удивлен, если base.js (который определяет
require
иexportSymbol
) не может работать с node.js ; они, по крайней мере, определяют и используют функцию «я в браузере?» и не затрагивают, например, функциональность DOM.