Улучшение отрисовки самого большого содержимого в экосистеме JavaScript.
В рамках проекта Aurora Google работает с популярными веб-фреймворками, чтобы гарантировать их хорошую работу в соответствии с Core Web Vitals . Angular и Next.js уже внедрили встраивание шрифтов, которое объясняется в первой части этой статьи. Вторая оптимизация, которую мы рассмотрим, — это критическое встраивание CSS, которое теперь включено по умолчанию в Angular CLI и находится в стадии разработки в реализации в Nuxt.js.
Встраивание шрифта
Проанализировав сотни приложений, команда Aurora обнаружила, что разработчики часто включают шрифты в свои приложения, ссылаясь на них в элементе <head>
index.html
. Вот пример того, как это будет выглядеть при включении Material Icons:
<!doctype html>
<html lang="en">
<head>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
...
</html>
Несмотря на то, что этот шаблон полностью действителен и функционален, он блокирует рендеринг приложения и вводит дополнительный запрос. Чтобы лучше понять, что происходит, взгляните на исходный код таблицы стилей, указанной в HTML выше:
/* fallback */
@font-face {
font-family: 'Material Icons';
font-style: normal;
font-weight: 400;
src: url(https://fonts.gstatic.com/font.woff2) format('woff2');
}
.material-icons {
/*...*/
}
Обратите внимание, как определение font-face
ссылается на внешний файл, размещенный на fonts.gstatic.com
. При загрузке приложения браузер сначала должен загрузить исходную таблицу стилей, указанную в заголовке.

Затем браузер загружает файл woff2
и, наконец, может приступить к рендерингу приложения.

Возможность оптимизации — загрузить начальную таблицу стилей во время сборки и встроить ее в index.html
. Это позволяет пропустить весь цикл обращения к CDN во время выполнения, сокращая время блокировки.
При создании приложения запрос отправляется в CDN, который извлекает таблицу стилей и встраивает ее в HTML-файл, добавляя <link rel=preconnect>
к домену. Применив эту технику, мы получим следующий результат:
<!doctype html>
<html lang="en">
<head>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin >
<style type="text/css">
@font-face{font-family:'Material Icons';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/font.woff2) format('woff2');}.material-icons{/*...*/}</style>
...
</html>
Встраивание шрифтов теперь доступно в Next.js и Angular
Когда разработчики фреймворка реализуют оптимизацию в базовом инструменте, они упрощают ее реализацию для существующих и новых приложений, обеспечивая улучшение всей экосистемы.
Это улучшение включено по умолчанию в Next.js v10.2 и Angular v11. Оба поддерживают встраивание шрифтов Google и Adobe. Angular ожидает, что последний будет представлен в v12.2.
Реализацию встраивания шрифтов в Next.js можно найти на GitHub , а также посмотреть видео, объясняющее эту оптимизацию в контексте Angular .
Встраивание критического CSS
Другое улучшение включает улучшение метрик First Contentful Paint (FCP) и Largest Contentful Paint (LCP) путем встраивания критического CSS. Критический CSS страницы включает все стили, используемые при ее первоначальном рендеринге. Чтобы узнать больше об этой теме, ознакомьтесь с разделом Defer non-critical CSS .
Мы заметили, что многие приложения загружают стили синхронно, что блокирует рендеринг приложения. Быстрое решение — загружать стили асинхронно. Вместо загрузки скриптов с media="all"
установите значение атрибута media
на print
, а после завершения загрузки замените значение атрибута на all
:
<link rel="stylesheet" href="..." media="print" onload="this.media='all'">
Однако такая практика может привести к мерцанию нестилизованного контента.
Видео выше показывает рендеринг страницы, которая загружает свои стили асинхронно. Мерцание происходит потому, что браузер сначала начинает загрузку стилей, а затем рендерит HTML, который следует за ними. Как только браузер загрузит стили, он запускает событие onload
элемента ссылки, обновляя атрибут media
на all
и применяя стили к DOM.
В течение времени между рендерингом HTML и применением стилей страница частично нестилизована. Когда браузер использует стили, мы видим мерцание, что является плохим пользовательским опытом и приводит к регрессиям в кумулятивном смещении макета (CLS) .
Критическое встраивание CSS вместе с асинхронной загрузкой стилей может улучшить поведение загрузки. Инструмент critters находит стили, используемые на странице, просматривая селекторы в таблице стилей и сопоставляя их с HTML. Когда он находит совпадение, он рассматривает соответствующие стили как часть критического CSS и встраивает их.
Давайте рассмотрим пример:
<head> <link rel="stylesheet" href="/styles.css" media="print" onload="this.media='all'"> </head> <body> <section> <button class="primary"></button> </section> </body>
/* styles.css */ section button.primary { /* ... */ } .list { /* ... */ }
Пример перед встраиванием.
В приведенном выше примере critters прочитает и проанализирует содержимое styles.css
, после чего сопоставит два селектора с HTML и обнаружит, что мы используем section button.primary
. Наконец critters встроит соответствующие стили в <head>
страницы, что приведет к следующему:
<head> <link rel="stylesheet" href="/styles.css" media="print" onload="this.media='all'"> <style> section button.primary { /* ... */ } </style> </head> <body> <section> <button class="primary"></button> </section> </body>
Пример после встраивания.
После встраивания критического CSS в HTML вы обнаружите, что мерцание страницы исчезло:
Критическая вставка CSS теперь доступна в Angular и включена по умолчанию в v12. Если вы используете v11, включите ее, установив свойство inlineCritical
в true
в angular.json
. Чтобы включить эту функцию в Next.js, добавьте experimental: { optimizeCss: true }
в ваш next.config.js
.
Выводы
В этой статье мы коснулись некоторых аспектов сотрудничества между Chrome и веб-фреймворками. Если вы являетесь автором фреймворка и узнаете некоторые из проблем, с которыми мы столкнулись в вашей технологии, мы надеемся, что наши выводы вдохновят вас на применение аналогичных оптимизаций производительности.
Узнайте больше об улучшениях . Полный список работ по оптимизации, которые мы проделали для Core Web Vitals, можно найти в посте Знакомство с Aurora .