Оптимизация скорости веб-сайта с помощью Lighthouse
В этом руководстве описано, как использовать Lighthouse и другие средства в Средствах разработки, чтобы найти способы ускорить загрузку веб-сайтов.
Средство Lighthouse предоставляет ссылки на содержимое, размещенное на сторонних веб-сайтах. Корпорация Майкрософт не несет ответственности и не контролирует содержимое этих сайтов и любые данные, которые могут быть собраны.
Предварительные условия
Установите Visual Studio Code для изменения исходного кода.
Установите Node.js , чтобы использовать его в качестве локального веб-сервера.
Введение
В этом руководстве вы улучшите производительность путешествия Margie, вымышленного веб-сайта для путешествий, содержащего изображения путешествий, текстовые описания, несколько взаимодействий с пользователями на основе JavaScript и интерактивную карту.
Исходные файлы для веб-сайта находятся на веб-сайте MicrosoftEdge / Demos > travel-site.
Шаг 1. Локальная настройка веб-сайта
Сначала настройте веб-сайт локально, чтобы вы могли внести в него изменения позже:
Получите исходный код веб-сайта локально: скачайте или клонируйте репозиторий демонстраций.
Откройте папку, только что скачаемую или клонированную в Visual Studio Code.
В Visual Studio Code выберите Просмотр>терминала. Или нажмите клавиши CTRL+'.
Visual Studio Code отображает исходные файлы на боковой панели Обозреватель и терминал:
В окне терминала введите
npx http-server
, чтобы запустить локальный веб-сервер.Этот локальный веб-сервер будет остановлен при закрытии Visual Studio Code.
В Microsoft Edge перейдите по адресу
http://localhost:8080/travel-site
, чтобы открыть веб-сайт:
Шаг 2. Аудит сайта
Всякий раз, когда вы хотите повысить производительность загрузки сайта, всегда начните с аудита.
Аудит выполняет две важные функции:
Он создает базовый план для измерения последующих изменений.
В нем содержатся практические советы о том, какие изменения повышают производительность больше всего.
Создание базовых показателей
Базовый план — это запись о том, как сайт работал до того, как вы улучшили производительность.
В Microsoft Edge откройте DevTools, щелкнув правой кнопкой мыши веб-страницу и выбрав пункт Проверить. Или нажмите клавиши CTRL+SHIFT+I (Windows, Linux) или COMMAND+OPTION+I (macOS).
В DevTools на панели инструментов main выберите вкладку Lighthouse. Если эта вкладка не отображается, нажмите кнопку Дополнительные вкладки (
") или кнопку Дополнительные инструменты (
") .
Выберите категорию Производительность и очистите все остальные категории. Пока оставьте другие параметры по умолчанию. Доступны следующие варианты:
Режим. Чтобы выполнять тесты во время загрузки веб-страницы, задайте для этого параметра значение Навигация (по умолчанию). Чтобы выполнять тесты в течение определенного периода времени, задайте для параметра Значение Timespan. Чтобы запустить тесты на веб-странице, как она отображается, задайте для параметра моментальный снимок.
Устройство. Чтобы имитировать строку агента мобильного пользователя и окно просмотра для мобильных устройств, задайте для этого параметра значение Mobile. Чтобы протестировать веб-страницу без имитации, задайте для этого параметра значение Desktop.
Категории: этот параметр позволяет выполнять только подмножество тестов, доступных в Lighthouse.
Щелкните Анализ загрузки страницы:
Через 10–30 секунд появится отчет о производительности сайта:
Обработка ошибок отчета
Если в отчете Lighthouse отображаются ошибки, попробуйте запустить Lighthouse еще раз в окне InPrivate без открытия других вкладок. Запуск Lighthouse из окна InPrivate гарантирует, что процесс аудита будет выполняться без помех.
Чтобы открыть окно InPrivate, выполните следующее :
Нажмите кнопку Параметры и прочее (...) на панели инструментов Microsoft Edge (над панелью инструментов разработки).
Щелкните Создать окно InPrivate.
Создайте новую базовую базу в Lighthouse:
Общие сведения об отчете
Общая оценка производительности
Номер в верхней части отчета — это общая оценка производительности веб-страницы. Позже, когда вы внесете изменения в код, отображаемое число должно увеличиться. Более высокая оценка означает лучшую производительность.
Метрики
В разделе Метрики представлены количественные показатели производительности веб-страницы:
Каждая метрика предоставляет представление о разных аспектах производительности. Например:
- First Contentful Paint указывает, когда содержимое впервые появляется на экране. Это важная веха в восприятии пользователем загрузки страницы.
- Время до интерактивного помечает точку, в которой отрисоченная страница готова к взаимодействию с пользователем.
Щелкните Развернуть представление , чтобы отобразить описание каждой метрики. Затем щелкните Дополнительные сведения , чтобы ознакомиться с документацией по этой теме:
Снимки экрана
Под разделом Метрики представлена коллекция снимков экрана, на которые показано, как выглядела страница во время загрузки:
Возможности
В разделе "Возможности " приведены конкретные советы по повышению производительности загрузки этой конкретной веб-страницы:
Щелкните возможность, чтобы отобразить дополнительные сведения о ней, а затем щелкните Подробнее , чтобы узнать о том, почему эта возможность важна, и конкретные рекомендации по ее устранению:
Диагностика
В разделе Диагностика содержатся дополнительные сведения о факторах, влияющих на время загрузки страницы:
Пройденные аудиты
В разделе Пройденные аудиты показано, что сайт делает правильно. Нажмите кнопку Показать , чтобы развернуть раздел:
Шаг 3. Эксперимент
В разделе Возможности отчета содержатся советы по повышению производительности веб-страницы. В этом разделе вы реализуете рекомендуемые изменения в базе кода, выполняя аудит сайта после каждого изменения, чтобы оценить, как это изменение влияет на скорость сайта.
Изменение размера изображений
Ваш отчет указывает, что обслуживание изображений соответствующего размера является одним из основных возможностей для повышения производительности страницы. Изменение размера образов помогает уменьшить размер полезных данных сети. Если ваш пользователь просматривает изображения на экране мобильного устройства шириной 500 пикселей, отправлять изображение шириной 1500 пикселей не имеет смысла. В идеале вы отправляете изображение не более 500 пикселей.
В разделе Возможности отчета щелкните Правильный размер изображений , чтобы отобразить изображения для изменения размера.
Lighthouse перечисляет четыре .jpg
файла, которые можно изменить, чтобы увеличить время загрузки:
Перед изменением размера этих изображений проверьте объем данных, которые сервер должен отправить в браузер, чтобы отобразить эти изображения:
Откройте средство "Сеть ".
Если инструмент пуст, обновите страницу.
В текстовом поле Фильтр введите
.jpg
, чтобы отфильтровать список запросов и отобразить только четыре изображения.Дополнительные сведения о фильтрации запросов в средстве "Сеть" см. в статье Фильтрация запросов в справочнике по сетевым функциям.
Проверьте нижнюю панель инструментов в средстве "Сеть" , чтобы проверить объем данных, передаваемых из-за изображений:
На нижней панели инструментов показано, что четыре изображения содержат 16,4 МБ из общего объема 17,3 МБ данных, переданных для этой веб-страницы.
Затем измените размер образов и выполните новый аудит:
В Visual Studio Code откройте
/travel-site/assets/img/optimized/
папку в Обозреватель, которая содержит копию четырех изображений, отображаемых на веб-странице, но уже оптимизированных для вас. Эти изображения имеют ширину 1000 пикселей и используют более оптимизированный.webp
формат.Изменение размера образов зависит от операционной системы. Например, для изменения размера образов в Windows можно использовать PowerToys. Дополнительные сведения см. в статье Служебная программа resizer.
/travel-site/index.html
Откройте файл и замените четыре пути к изображениям следующим образом:Замените четыре экземпляра
assets/img/
в файле наassets/img/optimized
.Замените четыре экземпляра
.jpg
в файле на.webp
.
В Lighthouse щелкните Выполнить аудит (
), чтобы вернуться на страницу main Lighthouse без потери базового отчета.
Нажмите кнопку Анализ загрузки страницы еще раз, чтобы узнать, как это изменение влияет на производительность нагрузки:
Ваш балл увеличился с 18 до 26. Чтобы проверить, сколько данных вы сохранили, используйте средство "Сеть" , как и раньше:
Теперь изображения на веб-странице требуют передачи только 360 КБ данных вместо 16,4 МБ.
Автоматическое изменение размера изображений
Для небольшого приложения достаточно выполнить однократное изменение размера, подобное этому. Но для большого приложения рассмотрите следующие стратегии управления образами:
Автоматическое изменение размера образов в процессе сборки.
Создайте несколько размеров каждого образа в процессе сборки, а затем используйте
srcset
в коде. Во время выполнения браузер определяет, какой размер лучше всего подходит для устройства. Дополнительные сведения см. в статье Адаптивные изображения на web.dev.Используйте CDN образа, которая позволяет динамически изменять размер изображения при запросе.
По крайней мере оптимизируйте каждое изображение. Это часто может создать огромную экономию.
Оптимизация означает запуск образа с помощью программы, которая уменьшает размер файла образа. Дополнительные советы см. в статье Оптимизация изображений в статье Быстрая загрузка в web.dev.
Сокращение неиспользуемых JavaScript
В последнем отчете Lighthouse говорится, что веб-страница содержит неиспользуемый код JavaScript и что загрузка этого кода только при необходимости приведет к уменьшению объема передаваемых данных при загрузке страницы.
Щелкните Уменьшить неиспользуемый Код JavaScript , чтобы отобразить файлы JavaScript, содержащие наиболее неиспользуемый код:
Сообщаемые файлы JavaScript относятся к домену www.bing.com
, что означает, что неиспользуемый код поступает из компонента карты Bing, используемого на веб-странице. Прокрутите вниз на демонстрационном веб-сайте Margie's travel , чтобы увидеть карту:
Чтобы подтвердить объем неиспользуемого кода и, возможно, найти другие неиспользуемые ресурсы, используйте средство покрытия :
В средствах разработки нажмите клавиши CTRL+SHIFT+P (Windows, Linux) или COMMAND+SHIFT+P (macOS), чтобы открыть меню Команд, начните вводить
Coverage
и выберите в списке пункт Показать покрытие .В средстве покрытия щелкните Начать инструментирование покрытия и обновите страницу (
"). Средство покрытия предоставляет общие сведения о том, сколько кода JavaScript и CSS, загруженного на страницу, фактически выполнялось.
Отчет о покрытии подтверждает, что зависимости карты Bing содержат код, который не будет использован при загрузке страницы. Карта на демонстрационном веб-сайте не отображается при первой загрузке страницы. Существует хорошая возможность повысить производительность, загружая карту Bing только тогда, когда этот раздел страницы становится видимым для пользователей.
Используйте API наблюдателя за пересечением, чтобы определить, когда карта становится видимой для пользователя. API наблюдателя пересечения позволяет наблюдать за изменениями в пересечении целевого элемента (в данном случае карта) с окном просмотра веб-страницы. Дополнительные сведения см. в разделе API обозревателя пересечений в MDN.
В Visual Studio Code откройте
/travel-site/index.html
файл и прокрутите вниз до нижней части файла. API карты Bing загружается с помощью тега<script>
:Под этой строкой находится еще одна строка, которая отвечает за настройку и загрузку карты в нужном месте:
<script src="assets/map.js"></script>
Удалите эти две строки и добавьте новую строку:
<script src="assets/map-on-demand.js"></script>
./travel-site/assets/map-on-demand.js
Откройте файл в Visual Studio Code и прочитайте код, чтобы понять, как он загружает и инициализирует компонент карты Bing. Ниже приведен фрагмент кода с описанием его работы:const MAP_CONTAINER_EL = document.querySelector('.place-discover-map'); const mapElIntersectionObserver = new IntersectionObserver(loadMapOnDemand); mapElIntersectionObserver.observe(MAP_CONTAINER_EL); let map = null; function loadMapOnDemand(entries) { if (map) { return; } if (!entries.some(entry => entry.isIntersecting)) { return; } const script = document.createElement('script'); script.type = 'text/javascript'; script.src = 'https://www.bing.com/api/maps/mapcontrol?callback=GetMap&key=Ap_eazGgpq5468v9MXr7Wu0zh30LQActgaT-tI_QxZQSm-Bd5qJxVKs_2B7NsqR4'; document.body.appendChild(script); } function GetMap() { /* ... */ }
Код инициализирует
mapElIntersectionObserver
переменную в новыйIntersectionObserver
объект . Затем этот наблюдатель начинает наблюдать за элементомMAP_CONTAINER_EL
, который является элементом на странице, которая должна содержать карту.По мере прокрутки пользователя запускается функция обратного
loadMapOnDemand
вызова наблюдателя. Эта функция ничего не делает, если карта уже существует или если элемент контейнера карты не пересекается с текущим окном просмотра.Если пользователь прокручивается до точки, когда элемент контейнера карты становится видимым в окне просмотра, и если карта еще не инициализирована, код создает новый
script
элемент, задает егоsrc
атрибут в API карты Bing и вставляет наscript
страницу.Остальная часть
map-on-demand.js
файла совпадает с файломmap.js
. Как только загрузит API карты Bing, запускаетсяGetMap
функция.GetMap
настраивает и отображает карту в элементе container.Сохраните изменения в Visual Studio Code, обновите веб-страницу в Microsoft Edge и выполните новый аудит в средстве Lighthouse, чтобы увидеть, как изменения влияют на производительность нагрузки:
Ваша оценка Lighthouse теперь на уровне 31, что является улучшением по сравнению с ранее, но есть больше вещей для оптимизации.
Устранение ресурсов, блокирующих отрисовку
Следующая возможность, отображаемая в разделе Возможности средства Lighthouse , связана с устранением ресурсов, блокирующих отрисовку.
Ресурс, блокирующий отрисовку, — это внешний файл JavaScript или CSS, который браузер должен скачать, проанализировать и запустить перед отображением страницы. Чем больше ресурсов, блокирующих отрисовку, необходимо обрабатывать при загрузке веб-страницы, тем дольше она должна отображаться в браузере. Попробуйте запустить только основной код CSS и JavaScript, необходимый для правильного отображения начального состояния страницы.
Первая задача заключается в поиске кода, который не требуется выполнять при загрузке страницы.
Щелкните Исключить ресурсы, блокирующие отрисовку , чтобы отобразить ресурсы, которые блокируют:
Lighthouse отображает список таблиц стилей, которые используются на демонстрационной веб-странице, например :
base.css
,home.css
иmap.css
.Снова откройте средство покрытия : нажмите клавиши CTRL+SHIFT+P (Windows, Linux) или COMMAND+SHIFT+P (macOS), введите Покрытие, а затем выберите Показать покрытие.
Нажмите кнопку Начать инструментирование покрытия и обновите страницу (
), чтобы отобразить отчет о покрытии, а затем введите
css
поле фильтра URL-адресов , чтобы отобразить только CSS-файлы:В отчете
contact-form.css
показано, что файлы иgallery.css
не используются вообще. Они оба имеют 100 % неиспользуемых байтов.contact-form.css
Щелкните файл в отчете. DevTools открывает файл в средстве "Источники ". Если строка кода выполнена, рядом с ней появится синяя полоса. Красная полоса означает, что строка кода не выполнялась и определенно не требуется при загрузке веб-страницы.В этом исходном файле отображаются только красные полосы, что означает, что веб-страница вообще не нуждается в этом файле.
Теперь удалите ссылки на эти файлы из кода:
В Visual Studio Code откройте
/travel-site/index.html
файл.В верхней части файла найдите список тегов
<link>
, которые загружают таблицы стилей на странице.Удалите две строки кода, которые загружают
contact-form.css
файлы иgallery.css
:Сохраните изменения в Visual Studio Code, обновите веб-страницу в Microsoft Edge и снова запустите новый аудит в средстве Lighthouse, чтобы увидеть, как изменения влияют на производительность нагрузки.
Автоматическое удаление некритических CSS
На предыдущем шаге оценка немного улучшилась, но Lighthouse по-прежнему помечает другие CSS-файлы как блокирующие начальную отрисовку страницы.
На веб-странице используются остальные CSS-файлы, поэтому их невозможно удалить. Однако их можно разделить на две группы:
Критический код CSS, который должен блокировать отрисовку веб-страницы, так как он визуально влияет на стиль и макет части веб-страницы, которую пользователи видят при ее загрузке.
Например, заголовок на веб-странице использует
header h1
правило CSS в/travel-site/assets/base.css
файле.Некритичный код CSS, используемый для отрисовки частей страницы, которые не видны при загрузке страницы.
Например, файл нужен только в том случае,
/travel-site/assets/desktop.css
если окно просмотра больше665px
.
Чтобы автоматически разделить код CSS таким образом, можно использовать средство Критическое . Дополнительные сведения см. в репозитории критически важных проектов.
Затем можно загрузить некритичный код CSS таким образом, чтобы не блокировать начальную отрисовку страницы. Дополнительные сведения см. в статье Отложить некритичное css на web.dev.
Кроме того, рекомендуется уменьшить код CSS и удалить ненужные пробелы и комментарии. Дополнительные сведения см. в статье Minify CSS at web.dev.
Уменьшение смещения макета путем явного задания ширины и высоты изображений
В отчете Lighthouse в разделе Диагностика предлагается явное определение width
и height
для элементов изображения. Щелкните Элемент Изображения не имеет явной ширины и высоты , чтобы отобразить дополнительные сведения:
В отчете говорится, что изображение в верхней части веб-страницы не имеет явных width
атрибутов и height
, что может привести к смене макета.
Сдвиги макета происходят, когда части веб-страницы изначально отображаются в одном месте, а затем перемещаются в другое положение во время загрузки страницы. Например, при загрузке изображения браузер не знает, сколько места для него нужно зарезервировать, пока изображение не будет полностью загружено.
Чтобы предотвратить смены макета, вызванные загрузкой изображений на веб-страницу, выполните одно из следующих действий:
- Определите
width
атрибуты иheight
каждого изображения в HTML-коде. - Зарезервируйте пространство в CSS с помощью
aspect-ratio
свойства CSS.
Дополнительные сведения см. в разделе Изображения без измерений в статье Оптимизация накопительного сдвига макета на web.dev.
На следующих шагах используйте aspect-ratio
свойство CSS, чтобы избежать смен макета.
В Visual Studio Code откройте
/travel-site/assets/home.css
файл и найдите правило CSS с селектором.hero-image img
.Измените правило CSS так, чтобы оно выглядело следующим образом:
.hero-image img { width: calc(100% + 2 * var(--main-margin)); position: relative; left: calc(-1 * var(--main-margin)); aspect-ratio: 1.5; object-fit: cover; }
До этого изменения правило CSS уже содержало
width
свойство, поэтому браузер знал, сколько горизонтального пространства нужно зарезервировать для изображения. Добавляяaspect-ratio
свойство, вы также указываете браузеру, сколько пространства по вертикали требуется зарезервировать. Добавляяobject-fit
свойство, вы избегаете искажения изображения, если его размеры CSS не соответствуют фактическим размерам файла изображения./travel-site/assets/desktop.css
Откройте файл и найдите правило CSS с тем же.hero-image img
селектором.Файл
desktop.css
используется только в том случае, если окно просмотра больше , если665px
веб-страница отображается на большом экране, например при использовании на ноутбуке.Измените правило CSS так, чтобы оно выглядело следующим образом:
.hero-image img { width: 100%; position: static; aspect-ratio: 2.5; object-fit: cover; }
На этот раз правило CSS уже было
width
определено иobject-fit
. Но вместо определенияmax-height
для образа используетсяaspect-ratio
свойство , чтобы убедиться, что браузер точно знает, сколько места нужно зарезервировать для изображения на настольных устройствах.Сохраните изменения в Visual Studio Code, обновите веб-страницу в Microsoft Edge и выполните новый аудит в средстве Lighthouse, чтобы увидеть, как изменения влияют на производительность нагрузки:
Теперь оценка до 37, но, что более важно, совокупная оценка смещения макета снизилась до 0, что означает, что при загрузке страницы больше нет сдвигов в макете.
Выполнение меньшей работы в потоке main
В последнем отчете отображаются значения метрик "Время в интерактивное " и "Общее время блокировки ", что означает, что на веб-странице по-прежнему есть что-то, что занимает много времени и не позволяет использовать страницу в течение нескольких секунд.
Прокрутите вниз до раздела Диагностика, в котором говорится, чтобы свести к минимуму работу main потока и сократить время выполнения JavaScript. В потоке main браузер выполняет большую часть работы, необходимой для отображения страницы, например:
- Синтаксический анализ и запуск HTML.
- Синтаксический анализ и применение CSS к элементам DOM.
- Запуск JavaScript.
В этом случае похоже, что самое большое узкое место заключается в том, что страница выполняет слишком много кода JavaScript при загрузке страницы.
Используйте средство "Производительность", чтобы проанализировать работу, выполняемую потоком main во время загрузки страницы, и найти способы отложить или удалить ненужные трудоемкие задачи:
Откройте средство производительности .
В средстве производительности нажмите кнопку Начать профилирование и перезагрузите страницу (
), а затем нажмите кнопку Остановить после полной загрузки страницы.
DevTools отображает визуализацию всех работ, выполненных браузером для загрузки страницы. Эта визуализация называется трассировки:
Трассировка показывает действие в хронологическом порядке слева направо. Диаграммы ЦП и NET в верхней части дают обзор активности ЦП и сети. Светло-коричневая область на диаграмме ЦП соответствует периоду времени, когда браузер был занят действиями по написанию скриптов. Эта область указывает на то, что вы можете ускорить загрузку страницы, выполняя меньше работы JavaScript.
Изучите трассировку, чтобы найти способы выполнения меньшей работы JavaScript.
В разделе Main показан хронологический журнал main активности потока слева направо. По оси Y (сверху вниз) показано, почему произошли события.
Например, на следующем рисунке браузер проводит большую часть времени в событии синтаксического анализа HTML . Пока это событие выполняется, веб-страница отображается не полностью. Это событие вызвало длительное событие Evaluate Script , соответствующее, когда браузер выполняет код JavaScript. Событие Evaluate Script привело (anonymous)
к выполнению функции, что привело к выполнению initRatings
функции:
Оптимизируйте функцию initRatings
, чтобы ускорить загрузку страницы:
В Visual Studio Code откройте
/travel-site/assets/rating.js
файл и прочитайте код.Код в этом файле отвечает за отображение пяти отзывов клиентов на веб-странице. Каждый отзыв имеет рейтинг, состоящий из нескольких звезд, цитаты и автора. Эти проверки поступают из API на стороне сервера, используемого
getRatings
в функции. ФункцияinitRatings
создает элементы DOM на странице для каждой проверки.В функции найдите
initRatings
способ ускорить выполнение кода JavaScript.Эта веб-страница — это всего лишь демонстрация, и
for
был введен цикл для замедления работы кода. На практике существует множество способов, как файл JavaScript, подобный этому, вызвать медленные загрузки страниц, например:- Слишком частый доступ к DOM.
- Выполнение тяжелых вычислительных задач.
- Использование больших библиотек Или платформ JavaScript.
for
Удалите цикл в началеinitRatings
функции, сохраните изменения и перезагрузите страницу в Microsoft Edge.Запустите новый аудит в средстве Lighthouse , чтобы увидеть, как изменения влияют на производительность нагрузки:
- Ваш счет поднялся до 92.
- Время интерактивной метрики снизилось до 1,3 секунды.
- Метрика Общего времени блокировки снизилась до 0 секунд.
Дополнительные сведения об анализе производительности страницы см. в справочнике по функциям производительности.
Выполнение меньшей работы в потоке main в реальном мире
Средство "Производительность " — это наиболее распространенный способ понять, какие действия выполняет веб-страница при загрузке, и найти способы удаления ненужных действий.
Если вы предпочитаете подход, который больше похож console.log()
на , API пользовательского времени позволяет произвольно пометить определенные этапы жизненного цикла приложения, чтобы отслеживать, сколько времени занимает каждый из этих этапов.
Веб-страницы часто загружаются медленно, когда они используют JavaScript для создания большинства пользовательских интерфейсов. Чтобы повысить производительность веб-страницы, рассмотрите возможность перемещения кода, который создает пользовательский интерфейс веб-страницы, на сторону сервера и доставки этого кода в браузер в виде HTML и CSS.
Сводка
- Всякий раз, когда вы настраиваете оптимизацию производительности загрузки сайта, всегда начните с аудита. Аудит устанавливает базовые показатели и дает советы по улучшению.
- Вносите одно изменение за раз и проводите аудит веб-страницы после каждого изменения, чтобы показать, как это изолированное изменение влияет на производительность.
Примечание.
Части этой страницы являются изменениями, основанными на работе, созданной и совместно используемой Google и используемой в соответствии с условиями, описанными в международной лицензии Creative Commons Attribution 4.0. Исходная страница находится здесь и автор Кейс Баски.
Эта работа лицензируется по международной лицензии Creative Commons Attribution 4.0.