[Из песочницы] Кеширование всего HTML и подключение JS «на ходу»
Однажды я совершил страшное дело — посмотрел исходный код главной страницы Яндекса и задумался — что-то тут не так. Я вижу 5 заголовков последних новостей, несколько картинок, поле поиска, ссылочки и вот вопрос: Где тут 700Кб, которые требуют 1,56с моего времени? Они в коде.Все мы ходим по сайтам, получаем килобайт полезной для себя или вообще воспринимаемой человеком информации и при скорости в 3Мбит/с тратим на это секунды. В этом посте я постараюсь описать, как передавать как раз только тот килобайт, который нужен человеку, а все остальное либо кешировать, либо вообще грузить только когда понадобится.
Первый на очереди к оптимизации — HTML Было бы неплохо кешировать весь HTML или хотя бы его большую часть — для этого можно использовать блочное кеширование: страницу разбиваем на блоки и эти блоки выносим в отдельный JS файл, который потом остается у пользователя. Плюс такого подхода в простоте, но в нашем случае будет нетривиальное решение — надо все немного усовершенствовать.Страницу можно не просто разбивать на блоки, а все в body заменить на XML структуру, соблюдая все отношения родительства — радикально и эффективно. Никаких стилей и излишеств. Для примера возьму код Яндекса для вывода 5-ти новостей:
- 1. Главная военная прокуратура признала законной амнистию Сердюкова …
var novosti='
- $HTML$
Оптимизация JS Если JS файл весит 100–200Кб, то его загрузка это около 0,5с. Он загрузится и останется в кеше, а вот задержка перед его выполнением все равно останется — это связано с тем, что JS файл сначала загружается, потом весь анализируется и только после этого начитает выполняться. Такая особенность позволяет, например, вызвать функцию еще до ее объявления. Чем больше файл — тем дольше аналаз, до 300 мс, а иногда и больше. Есть очень хороший способ сократить время — сделать файл дискретным: разбить на отдельные функции или просто части и подключать их, когда они нужны. Они так же будут кешироваться, только время их анализа будет гораздо меньше — в пределах 1–2 мс.Пусть у нас есть функция, которая в реальном времени подключает JS файлы, например, вот такого вида:
inc ({ //список подключаемых функций/файлов вида name:'id' — name-название функции (для вызова), id-постфикс для файла }, function () { //JS с использованием подключенных функций и файлов }); Для нее есть несколько требований. Во-первых, она должна запоминать уже подключенные функции и файлы, во-вторых поддерживать загрузку из разных каталогов, а так же быть асинхронной. Для указания каталога можно использовать глобальную переменную includesrc=«любойсайт.ру/каталог/» для подключения файлов и «любойсайт.ру/каталог/функция_» для функций — к этому пути будет добавляться id (постфикс). Допустим, что надо разбить файл на несколько частей или функций, тогда полученные файлы должны быть примерно такого вида:
//если файл с одной функцией, то ludes[«id»]=function (a1, …, aN){ //код }
//если с несколькими: //функции (просто часть исходного файла) ludes[«id»]++;//id — это имя файла, без расширения Таким образом, в файле с функцией должна быть указана часть имени файла, а при подключении файла — его название, только без расширения.
ESS Выше я написал, как можно вынести весь HTML и кешировать, передавать только нужную информацию в XML виде, потом написано, как можно свести задержку перед выполнением JS к нескольким миллисекундам, но нет самого решения проблемы — вот оно. Его можно назвать ESS — Easy Stylesheets, по аналогии с CSS. Состоит из 2+1 функций.ess (a, b); — функция, заменяющая XML блоки на странице шаблонами из JS файла, ей надо передать a — элемент DOM и b — строчку-шаблон.inc (); — уже упомянутая функция, которая позволяет асинхронно подключить любой файл, с любого домена и затем продолжить работу.И вспомогательная функция g (a, b, c); — ищет объект по строчкам CSS вида. a — с каким tag/#id/@ name/.class искать объект, b — в каком объекте искать и с — флаг 0/1, указывающий, надо ли в любом случае возвращать массив.
Для ESS есть документация, в которой описан синтаксис и наглядные примеры использования. Функции ess () и inc () не только позволяют экономить время пользователя и снижает нагрузку на сервер, они так же открывают новые возможности для программирования на JS, но это уже тема для отдельной статьи.