Это очень интереснаяNon-mainstream frontend fieldобласть. Она исследует, как использовать инженерные методы для решения комплексной задачи оптимизации фронтенд-разработки и развёртывания. Я учусь и практикуюсь с тех пор, как пришёл в индустрию.
По моему впечатлению, Facebook — пионер в этой области. Те, кому интересно и у кого есть VPN, могут посмотреть исходный код страницы Facebook и понять, что такое инженерия на самом деле.
Далее я хочу объяснить с точки зрения принципов. Здесь много изображений и довольно длинно; надеюсь, у вас хватит терпения дочитать до конца.
Давайте вернёмся к основам и начнём с примитивной фронтенд-разработки. На картинке выше — «милая» страница index.html и её файл стилей a.css. Пишете код в текстовом редакторе, компиляция не требуется, просматриваете локально, убеждаетесь, что всё в порядке, выкладываете на сервер и ждёте, пока пользователи зайдут. Фронтенд — это так просто, так весело, порог входа настолько низкий, что его можно выучить за минуты, да?!
Затем мы открываем страницу, видим результат и проверяем сетевой запрос: 200! Неплохо, чертовски идеально! Итак, разработка завершена... готово?
Подождите, это ещё не всё! Для крупных компаний безумный трафик и метрики производительности сделают фронтенд совсем не «весёлым».
Посмотрите на запрос a.css. Если он загружается каждый раз, когда пользователь заходит на страницу, разве это не влияет на производительность и не расходует пропускную способность? Мы надеемся, что будет так:
Использовать 304, чтобы браузер использовал локальный кеш. Но этого достаточно? Нет! 304 называется согласованным кешированием; всё равно приходится один раз связаться с сервером. Наш уровень оптимизации безумен, поэтому мы должны полностью устранить этот запрос, сделав так:
Заставить браузер использовать локальный кеш (cache-control/expires), без обмена с сервером. ОК, оптимизация на стороне запросов достигла безумного уровня, но вот вопрос: если не позволять браузеру отправлять запросы за ресурсами, как тогда обновляется кеш?
Хорошо, полагаю, кто-то уже придумал решение:Обновляя пути к ресурсам, на которые ссылается страница, браузер заставляют добровольно отказаться от кэша и загрузить новые ресурсы.Вот так:
В следующем релизе меняем адреса ссылок на новые версии, и ресурсы обновляются, верно? ОК, проблема решена?! Конечно нет! Безумие крупных компаний снова даёт о себе знать. Подумайте о такой ситуации:
Страница ссылается на 3 CSS-файла, но в некотором релизе был изменён только a.css. Если обновить версии всех ссылок, кэши b.css и c.css тоже будут аннулированы. Разве это снова не расточительно?!
Снова включаем режим безумия, и мы легко видим, что для решения этой проблемы изменения URL должны быть привязаны к содержимому файла. То есть только при изменении содержимого файла меняется соответствующий URL, что позволяет достичь точного управления кэшем на уровне файлов.
Что связано с содержимым файла? Естественно, мы думаем об использовании алгоритма вычисления дайджеста данных для вычисления дайджест-информации файлов. Поскольку дайджест-информация взаимно однозначно соответствует содержимому файла, теперь у нас есть основа для управления кэшем с точностью до отдельных файлов. ОК, давайте изменим URL так, чтобы они включали дайджест-информацию:
На этот раз при изменении файла обновляется только URL, соответствующий этому файлу. На данный момент это кажется идеальным. Думаете, этого достаточно? Крупные компании говорят вам: слишком молод, слишком прост!
Вздох~~~~, дайте мне отдышаться.
Чтобы ещё больше повысить производительность сайта, современные интернет-компании развёртывают статические ресурсы и динамические веб-страницы в отдельных кластерах. Статические ресурсы развёртываются на CDN-узлах, а ресурсы, на которые ссылаются веб-страницы, также становятся соответствующими путями развёртывания:

ОК, когда мне нужно обновить статические ресурсы, я также обновляю ссылки в HTML, верно? Вот так:
В этом релизе были изменены как структура страницы, так и стили, а также обновлены URL-адреса статических ресурсов. Теперь пора развернуть код. Дорогой фронтенд-разработчик, скажи мне: что нам развертывать первым — страницы или статические ресурсы?
Deploy the pages first, then deploy the resources: В интервале времени между двумя развертываниями, если пользователь посещает страницу, он загрузит старые ресурсы в новой структуре страницы и закэширует эту старую версию как новую. В результате пользователь видит страницу со сломанными стилями. Если он вручную не обновит страницу, она будет работать неправильно, пока кэш ресурсов не истечет.Deploy the resources first, then deploy the pages: В течение интервала развертывания пользователи с локальным кэшем старых ресурсов заходят на сайт. Поскольку запрашиваемая страница — старой версии, а ссылки на ресурсы не изменились, браузер напрямую использует локальный кэш, поэтому страница отображается нормально. Но пользователи без локального кэша или с истекшим кэшем увидят, как старая страница загружает новые ресурсы, что вызовет ошибки выполнения страницы. Как только развертывание страницы завершится, у этих пользователей все вернется в норму при следующем посещении. Итак, весь этот анализ выше означает: развертывание любого из них первым не сработает! Оба варианта вызовут путаницу на странице во время развертывания. Поэтому для проектов с низким трафиком можно заставить разработчика немного пострадать, тайно развернуть все глубокой ночью: сначала выложить статические ресурсы, затем развернуть страницы — так, похоже, возникает меньше проблем.
Однако большие компании совершенно безумны; не существует такого «абсолютного периода низкой нагрузки», есть только «относительный период низкой нагрузки». Поэтому ради стабильного сервиса мы должны продолжать стремиться к совершенству!
Эта странная проблема возникает из-за публикации ресурсов в стиле перезаписи. Перезапись уже опубликованных ресурсов ресурсами, которые только предстоит опубликовать, и вызывает эту проблему. Решить ее просто: реализовать публикацию без перезаписи.
Посмотрите на рисунок выше. Используйте дайджест-информацию файла, чтобы переименовать файлы ресурсов, и поместите дайджест-информацию в путь публикации файла ресурса. Таким образом, ресурсы с изменённым содержимым становятся новыми файлами, публикуемыми онлайн, без перезаписи существующих файлов ресурсов. При развертывании сначала полностью разверните статические ресурсы, затем выполните серое развертывание страниц, и вся проблема решается довольно идеально.
Поэтому решение по оптимизации статических ресурсов в крупных компаниях в основном должно реализовывать следующие вещи:
- Настройте очень долговременный локальный кеш — экономия пропускной способности, повышение производительности
- Используйте дайджесты содержимого как основу для обновления кеша — точное управление кешем
- Развертывание статических ресурсов на CDN — оптимизация сетевых запросов
- Изменяйте пути публикации ресурсов, чтобы реализовать публикацию без перезаписи — плавные обновления
Выполнение всего набора даёт относительно полное решение для управления кешированием статических ресурсов. Также обратите внимание, что управление кешированием статических ресурсов требует, чтобывсе места, где во фронтенде загружаются статические ресурсы, обрабатывались именно так. Да, все они! Не говоря уже о JS и CSS, это также должно включать пути к ресурсам, на которые ссылаются в JS- и CSS-файлах. Поскольку задействована дайджест-информация, дайджест-информация ресурсов, на которые ссылаются, также изменяет содержимое самого ссылающегося файла, создавая каскадные изменения дайджеста. Примерная схема будет такой:
Итак, мы быстро узнали об оптимизации и проблемах развертывания, с которыми сталкивается фронтенд-инжиниринг при кешировании статических ресурсов. Теперь возникает новая проблема: как, чёрт возьми, инженеры должны писать такой код!!!
Чтобы объяснить комбинированный подход оптимизации и инжиниринга, возникнет куча инженерных вопросов, таких как модульная разработка, загрузка ресурсов, объединение запросов, фронтенд-фреймворки и так далее. Вышесказанное — только начало; решение — это суть, но об этом можно сказать гораздо больше. Я буду постепенно раскрывать это, когда будет время.
Короче говоря, оптимизация производительности фронтенда — это определённо инженерная задача!
Вышесказанное — не только мои домыслы. Вы можете посмотреть страницы и исходный код статических ресурсов Baidu или Facebook, изучить обработку путей к ресурсам и управление кэшированием статических ресурсов в сетевых запросах. Ещё раз восхищаюсь уровнем фронтенд-инжиниринга Facebook; я в восхищении.
Я советую фронтенд-разработчикам уделять больше внимания области фронтенд-инжиниринга. Некоторые могут подумать, что их продукты малы и не нуждаются в таком безумии, но вполне вероятно, что однажды вам понадобится внести такие изменения. К тому же, если мы можем делать вещи более совершенно, почему бы и нет?
Также не думайте, что это проблемы, которые должны решать операционные инженеры или бэкенд-инженеры. Если их оставить другим ролям,Все склонны перекладывать проблемы, которые их не волнуют, на других., то процесс разработки фронтенд-разработчиков будет сильно ограничен. Такая ситуация не редкость даже в некоторых крупных компаниях!
Источник: http://www.zhihu.com/question/20790576/answer/32602154