Дерево зависимостей javascript

WMix

герр M:)ller
Партнер клуба
Очень устал от пойска ошибок из-за дублирующихся или нехватающих библиотек при подключении javascript библиотек.. хочется упростить себе работу создав дерево зависимостей..

проблема
во время написания view скрипта в какой-то момент мы понимаем что нужен к примеру Autocomplete
чтоб правильно подключить Autocomplete необходимы UI библиотеки position, widget и core которые в свое время зависят от самого jquery..
простое решение
по простому можно сложить весь UI в один пакет и подключать его на всех страничках, но используется не только эти библиотеки, но и множество других, это и WYSIWYG редакторы, и colorpicker и webcam и и и...
помимо этого у большинства view есть свой скриптик, а также может быть некоторая библиотека из множества файлов из которой нужен для данного view только один...
сложное решение
есть helper которому можно сказать, какая библиотека необходима, в процессе выполнения скрипта,
PHP:
$this->headRessouce()->add( 'autocomplete', 'js' );
таким образом собирается набор необходимых библиотек, и во время рэндинга создается ссылка на некий пхпфайл
к примеру так.
PHP:
<script type="text/javascript" src="js.php?g=autocomplete,webcam"></script>
js.php читает конфигурацию (тут как раз хочется зависимости добавить), и понимает какой набор файлов необходим
PHP:
	autocomplete.0		= "js/jQuery/jquery-1.5.2.js"
	autocomplete.1		= "js/jQuery/ui/jquery.ui.core.js"
	autocomplete.2		= "js/jQuery/ui/jquery.ui.widget.js"
	autocomplete.3		= "js/jQuery/ui/jquery.ui.position.js"
	autocomplete.4		= "js/jQuery/ui/jquery.ui.autocomplete.js"
весь список передается дальше на minify который генерит сжатый файл, кэширует его и отдает клиенту (кстати решаются проблемы дубликатов)...
теперь о проблемах данного подхода.. для того чтобы все коректно работало необходимо чтоб все библиотеки подключались в определенной последовательности. в случае если зависимая библиотека подключена после скрипта котоый ее использует, может возникнуть ошибка.

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

Adelf

Administrator
Команда форума
зависимостями управляют на стороне js, который легко может грузить необходимое налету. Реализации есть у многих больших библ.
 

WMix

герр M:)ller
Партнер клуба
Adelf
научи, или слово для пойска скажи...
 

WMix

герр M:)ller
Партнер клуба
Redjik
уже интересно, конфиг очень на мой похож... интересно только создать дерево, остальное уже существует
 

WMix

герр M:)ller
Партнер клуба
да это node.js тоже вариант конечно, но возможно можно обойтись без доп сервера... я и less хочу на php решать
 

fixxxer

К.О.
Партнер клуба
и будешь каждый раз вместо отдачи статического файла дергать php? это ты не очень хорошо придумал

есть два подхода
1) require.js
2) собираем все в одну (или несколько) пачек при деплое (minify *.js), на девеле тупо подключаем все скрипты пачки и хрен с ним
 

fixxxer

К.О.
Партнер клуба
а less можно прекрасно собирать в шаблоне хелпером, отдавая ссылку на сбилженный css (обрати внимание на cachedCompile в lessphp)
 

WMix

герр M:)ller
Партнер клуба
на самом деле собрался пхп дергать, но пхп понимает что есть готово сгенеренный файл
PHP:
if(file_exists(md5($_SERVER['REQUEST_URI'])))
и просто читает его...
 

fixxxer

К.О.
Партнер клуба
это операция на порядок более тяжелая чем отдать статику веб-сервером
 

WMix

герр M:)ller
Партнер клуба
Код:
GET /min/index/js/anF1ZXJ5LHdlYnNvY2tldA== HTTP/1.1
Host: ff.mars.local
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:17.0) Gecko/17.0 Firefox/17.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: ......
Cookie: FFSS=g95p10cpbih2hckq1020sss621
If-Modified-Since: Tue, 13 Mar 2012 15:27:36 GMT
If-None-Match: "pub1331652456;gz"
Cache-Control: max-age=0

HTTP/1.0 304 Not Modified
Date: Tue, 11 Dec 2012 16:30:58 GMT
Server: Apache/2.2.14 (Ubuntu)
Connection: close
Etag: "pub1331652456;gz"
Expires: Wed, 11 Dec 2013 16:30:58 GMT
Cache-Control: max-age=31536000, public
Vary: Accept-Encoding
да я это осознаю, но также понимаю что это произойдет 1 раз
 

fixxxer

К.О.
Партнер клуба
а) я про РАЗНЫХ пользователей, причем тут 304?

б) итак кто шибко умный - я намеренно упрощаю

ситуация 1. отдача статики. реверс-прокси (nginx, lighty, squid...) делает вызов sendfile(), обратабывая все в своем event loop, mod_php вообще не заюзан
либо, если нет реверс-прокси, апач достаточно умный чтобы просто сделать sendfile()

ситуация 2. инициализируем пхп реквест, запускаем zend engine, выполняем байткод, readfile()-ом копируем кусочками в апачевый буфер, откуда уже только отдаем клиенту...

да просто на самом то деле возьми ab и сделай тест двух случаев и сравни RPS =)
 

WMix

герр M:)ller
Партнер клуба
хорошо, попробую согласиться, и немножко изменю подход, собрав 2 варианта, твой и мой вместе
собираем все в одну (или несколько) пачек при деплое (minify *.js), на девеле тупо подключаем все скрипты пачки и хрен с ним
итак, заранее известно, как будет/должен называться js файл,
PHP:
<script type="text/javascript" src="/js/<?=md5( 'autocomplete,webcam' )?>.js'"></script>
чтото вроде этого... он уже сгенерен и лежит в паблик папочке... все равно остается проблема зависимостей
 

fixxxer

К.О.
Партнер клуба
ну берешь свое дерево зависимостей

делаешь в шаблоне взыов хелпера типа

{{ JsCompiler.build('autocomplete', 'webcam') }}

там резолвишь зависимости, генеришь имена, компиляешь при необходимости, возврашаешь script теги
 

Ярослав

Новичок
и будешь каждый раз вместо отдачи статического файла дергать php? это ты не очень хорошо придумал
А почему не сделать через .htaccess?

PHP:
RewriteEngine On

RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^.*$ - [NC,L]

RewriteRule ^(.+)-v([0-9]+\.[0-9]+\.[0-9]+)\.js$ скрипт для генерации.php?p=$1&v=$2 [NC,L]
Пример, если мы запрашиваем файл
autocomplete-v1.2.1.js и он есть, то он сразу и отдается, иначе реврайтим на скрипт который генерит, запишет в кеш, и сразу отдаст контент

UPD: 1.2.1 это версия апликейшена. Когда выходит новая версия, увеличиваем, к примеру 1.2.2, а все кэши *-v1.2.1 удаляем
 

fixxxer

К.О.
Партнер клуба
если завязано на версию аппа, в сто раз проще генерить при деплое и всё

детский сад, заливающие цмс по фтп, может делать как угодно конечно
 

WMix

герр M:)ller
Партнер клуба
fixxxer
я еще раз хочу подумать, итак, накидал ключей в helper, при рендинге¹ получил ссылку на готовый md5(keys).js а далее если вдруг окажется что библиотека не собранна, какие действия?
если взять мысль Ярослава, то тоже позняк метаться, ключей уже нет...
¹ можно проверить в эту секунду на наличие готового файла, и в злучае его не существования отдать задачу демону нагенерить...
конечно демон справится с задачей позже... еще на уровне хелпера перереврайтить на страничку ожидания? тоже бред...

как делают то правильно, node.js или всеже то что я задумал нормальная реализация?
 
Сверху