Skip to content

Instantly share code, notes, and snippets.

@Inviz
Created March 12, 2009 11:28
Show Gist options
  • Select an option

  • Save Inviz/78027 to your computer and use it in GitHub Desktop.

Select an option

Save Inviz/78027 to your computer and use it in GitHub Desktop.
Dependancy manager
Задача: Отдать как можно больше файлов за один реквест. Шарные файлы отдавать отдельно, чтобы они закешировались через http.
Должен интеллектуально раздавать недостающие клиенту файлы и наборы файлов. Должен уметь собирать их в один респонс, знать когда их паковать в один, а когда по отдельности. Должен уметь сжимать гзипом с возможностью подключения консольных утилит для сжатия.
1) Зависимости регистрируются на сервере в виде хеша. У зависимости должен быть alias и может иметься несколько файлов, которые будучи загруженными в правильном порядке зависимость удовлетворяют.
2) Дерево зависимостей должно уметь экспортироваться в JSON, который можно будет отдать клиенту, чтобы он тоже мог запрашивать то что ему нужно.
3) Если на файл ссылается только одна зависимость, он конкатенируется и отдается вместе с остальными файлами. Если на файл ссылаются несколько зависимостей, то исходя из желания использовать HTTP-caching, мы должны отдать его отдельно. В экспортированном в JSON дереве зависимости уже должны быть собраны как нужно. Клиент не должен знать, что mootools состоит из 20 файлов.
4) Менеджер должен уметь сгенерить дерево с путями содержащими таймстаймп (mootools.js?123456789) и уметь глядеть на время обновления зависимых файлов. Кроме того, в зависимости от енвайромента, должно уметь генерить пути без query string, а взамен отдавать правильные таймстампы в хедерах (Last-Modified).
5) Зачастую виджеты состоят из CSS и JS файлов Менеджер должен уметь вывести зависимые файлы (CSS и картинки внутри CSS) внутрь JS файла. В зависимости от возможностей браузера (браузер будет сам говорить, что он может через X-хедеры):
- Картинки енкодятся через base-64 и выводятся в CSS. Для этого стайлшиты будут оформлены соответствующим образом (см. пример 3)
- ЦСС шринкается и выводится в JS (см. пример 4). Случается это только тогда, когда на этот CSS файл ссылается только одна зависимость. И в таком случае, экспортированное дерево не содержит этот CSS-файл.
6) Менеджер должен уметь прогонять полученные js-файлы через что-нибудь консольное вроде YUI-compressor.
Итого:
Всё таки для того чтобы достичь максимальной кешируемости, придется отказаться от самых диких идей которые у меня были. При текущей описанной схеме, достаточно будет собирать файлы при деплое. Но для некоторых из файлов придется генерить несколько вариантов, например mochaui-with-stylesheets.js, mochaui-with-stylesheets-and-images.js и mochaui.js и отдавать тот, который больше подходит по фичам, которые поддерживает браузер юзера.
Чем это отличается от предупаковки? Тем что мы упаковываем и CSS и картинки и JS в один файл. Причем для плохих браузеров (ie7), мы картинки не упаковываем. Плюс мы собираем файлы специально для текущего браузера:
Пример:
{
'mootools': {
'mootools/Core/Core.js',
...
'mootools.css', //внутри обращения на бандл картинок logo.png и button.png
'mootools-ie7'
}
}
GET mootools.js, Useragent: IE7
Ответ: mootools/Core/Core.js + ... + mootools.css + mootools-ie7.css
GET mootools.js, Useragent: FF3
Ответ: mootools/Core/Core.js + ... + mootools.css + logo.png + button.ong
Мы можем не ориентироваться на User-agent, а я могу слать параметр ?for=trident, ?for=gecko или ?for=webkit (+ presto для оперы)
Примеры использования на клиенте:
1) Регистрация зависимостей:
{
...
'mootools-core': [
'/vendor/mootools-core/Core/Class.js',
'/vendor/mootools-core/Core/Native.js'
...
],
...
'mochaui': [
'/vendor/mochaui/mochaui.css', //css file to be embedded
'/vendor/mochaui/Core/Window.js'
...
],
'validated-forms': [
'/vendor/forms/icons.png'
]
...
}
2) Получение файлов:
using('mootools-core', function() {
...
})
3) CSS оформленный на отдачу картинок в base64 (слова в комментариях могут отличаться)
/* Embed these images if possible */
.cross { background-image: url('/images/cross.png)}
.button { background-image: url('/images/button.png)}
/* Thank you */
=>
/* These images were embedded */
.cross { background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA...);}
.button { background-image:url(data:image/png;base64,iVBORw0hEUgAAADIKGgoAAAANSUA...);}
4) CSS внутри JS
new Asset.Inline.css(".cross { background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA...);}.button { background-image:url(data:image/png;base64,iVBORw0hEUgAAADIKGgoAAAANSUA...);}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment