Ответ 1
Изменить (2012 октябрь): Теперь ASP.NET 4.5 включает Связывание и минимизация. Текущая версия не поддерживает динамическое генерирование javascript очень хорошо, но в остальном она довольно удобна и, например, наблюдает за изменениями в файловой системе, как описано ниже; перед запуском собственного сжатия, попробуйте это!
Старый ответ:
Вместо того, чтобы реализовать это во время сборки, я предлагаю вам сделать это во время выполнения. Это имеет ряд преимуществ:
- Вы можете включить параметры отладки, которые отключают объединение и минимизацию, чтобы упростить идентификацию ошибок. Это также позволяет работать с меньшей разницей между средой разработки и производства.
- Вы получаете некоторую гибкость. Я дважды исправлял ошибки с помощью script -одного исправления, которое может напрямую работать прямо. Для простых, но критических ошибок это хороший вариант.
- Совсем немного проще реализовать - у вас уже есть опыт в реализации ответов на http, которые здесь очень приятны.
- Вы можете отслеживать дату последнего изменения сценариев, и не только использовать это для установки соответствующих ETags и whatnot (что может сделать IIS), а скорее установить дату истечения срока действия в будущем. Затем вместо того, чтобы связывать фактический scipt (независимо от того, минитизирован или нет), вы можете связать script с коротким токеном в querystring - таким образом клиентам не нужно проверять, обновил ли js. Когда это произойдет, страницы будут ссылаться на "новый" script файл, который нужно отдельно запросить. (Это можно сделать в скриптах сборки, но сложнее).
- Процесс сложной сборки часто имеет скрытые затраты. Для запуска не требуется больше времени, но что происходит, когда вы хотите обновить инструмент автоматизации сборки? Когда вы переключаете IIS или версии Windows? Когда вы переходите на VS 2010? Насколько легко довести новых разработчиков до скорости?
Это грубая схема процесса, который я следую:
- Я указываю две директории, содержащие только сжимаемые css и js. В экземпляре appdomain или вскоре после этого через статический конструктор класс находит содержимое этих каталогов и создает
FileSystemWatcher
для просмотра изменений. - Все файлы читаются в порядке имени файла (использование префиксов, таких как
00_jquery.js
10_init.js
и т.д., помогает контролировать порядок здесь). Список имен файлов хранится для целей отладки. - Все файлы объединяются с помощью конкатенации строк, затем минимизируются с помощью YUI, затем сжимаются через
GZipStream
. Специфический токен версии вычисляется либо с помощью последней даты последнего изменения, либо с помощью хеша результата. - Результат сжатия (байтовый массив, имена файлов и токен, зависящий от версии) сохраняется в переменной статического класса (защищенном
lock
). Если наблюдатель файловой системы обнаруживает обновление, шаг 2 запускается снова и выполняется в фоновом режиме до завершения сжатия - следовательно, блокировка. - Любая страница, желающая включить объединенный javascript (и/или css), вызывает общую статическую переменную. Если мы находимся в режиме отладки, который генерирует тег script (или link) для каждого имени файла, как это было на втором шаге, в противном случае это генерирует один тег script (или link) в Uri, который обрабатывается пользовательским
IHttpHandler
. Все Uri включают маркер, зависящий от версии, в querystring - это игнорируется как обработчиком статических файлов IIS, так и настраиваемым обработчиком HTTP для комбинированной мини-версии, но упрощает кэширование. - В пользовательском IHttpHandler, когда получен запрос на комбинированный javascript (или css), заголовок Content-Encoding: gzip установлен и датой истечения срока действия в будущем. Затем предварительно сжатый массив байтов записывается непосредственно в HTTP-поток через
context.Response.OutputStream
.
Используя этот подход, вам не нужно возиться с параметрами web.config всякий раз, когда вы добавляете или удаляете файл script; вы можете обновлять скрипты во время работы приложения, и клиенты будут запрашивать их на самом следующем представлении страницы, но вы по-прежнему будете получать оптимальное поведение кэша, поскольку браузеры даже не отправят запрос If-Not-Modified из-за заголовка истечения срока действия. Обычно сжимающие скрипты должны занимать секунду или около того, а сжатый результат должен быть настолько мал, что накладные расходы на память статической переменной незначительны (не более 100 КБ для действительно большого количества сценариев/css).