Рекомендуется потратить время на чтение, чтобы углубить свои знания в области оптимизации производительности изображений перед интерфейсом 😜
1. Введение
Мы знаем, что одним из показателей оптимизации производительности является скорость открытия веб-страниц, поскольку быстрая отрисовка веб-страниц может повысить удобство работы пользователей. Но когда скорость сети не сильная, неизбежна проблема загрузки ресурсов. Особенно при загрузке изображений в этой статье в основном обсуждаются некоторые вопросы оптимизации производительности, связанные с загрузкой изображений.
Сначала ознакомьтесь с полным текстом знаний 👇 (в резюме после статьи есть конкретные категории)
2. Оптимизация производительности загрузки изображений
2.1 Ленивая загрузка изображений
2.1.1 Зачем использовать ленивую загрузку? 🧐
Создаем новый html файл, сначала загружаем 3 изображения, чтобы увидеть его сетевой запрос. Используйте live-сервер, чтобы открыть страницу и проанализировать проблемы с производительностью, связанные с протоколом http на веб-стороне.
<body>
<div class="container">
<div class="img"><img src="https://img.36krcdn.com/20210122/v2_7d557e30f1254bdc8597f5eccdeb8e29_img_png?x-oss-process=image/resize,m_mfit,w_600,h_400,limit_0/crop,w_600,h_400,g_center" alt="加载中" class="pic"></div>
<div class="img"><img src="https://img.36krcdn.com/20210122/v2_8327e6797c2745f99e8ecc6bae1958b4_img_png" alt="加载中" class="pic"></div>
<div class="img"><img src="https://img.36krcdn.com/20210122/v2_6c513ab4937d456d9554deca27e9f5f0_img_000?x-oss-process=image/resize,m_mfit,w_600,h_400,limit_0/crop,w_600,h_400,g_center" alt="加载中" class="pic"></div>
</body>
Как видите, три загруженных здесь изображения сделали три сетевых запроса. Каждый img будет открывать http-канал независимо, что является очень хорошей производительностью, потому что в это время на странице есть 3 одновременных HTTP-номера.
Когда у нас есть большое количество изображений, если мы запрашиваем все ресурсы изображения каждый раз, когда заходим на страницу, это окажет большое давление на браузер, и в то же время пользователь может уже уйти после того, как изображения загружен.
Следовательно, что нам нужно сделать, так это свести к минимуму количество параллелизма.只请求可视区域的图片资源
2.1.2 Принцип реализации ленивой загрузки😏
Источником изображения в основном является атрибут src
Когда мы заменяем src на data-src, отправляет ли браузер запрос, зависит от наличия атрибута src. Таким образом, в настоящее время на странице не будет того же запроса изображения, что и сейчас.
<body>
<div class="container">
<div class="img"><img data-src="https://img.36krcdn.com/20210122/v2_d4fac7849276424f89522946e8ffb128_img_000?x-oss-process=image/resize,m_mfit,w_600,h_400,limit_0/crop,w_600,h_400,g_center" alt="加载中" class="pic"></div>
</div>
</body>
Таким образом, мы можем воспользоваться этим, когда мы не входим в видимую область, мы сначала даемЗаметке присваивается атрибут data-src, который выдается после входа в визуальную областьПримечания назначения атрибута src, введите исходящие сетевые запросы.
Зона визуальной концепции
Видимая область — это просто область, которую вы можете видеть. Часть окна браузера, в которой отображается веб-страница (то есть за исключением адресной строки и панели инструментов), является видимой областью. Практичное JavaScript-решение для получения ширины и высоты визуальной области в разных браузерах:
var w = document.documentElement.clientWidth ||
document.body.clientWidth;
var h = document.documentElement.clientHeight ||
document.body.clientHeight;
Связанные API
- добавитьEventListener:
Метод EventTarget.addEventListener() регистрирует указанный слушатель в EventTarget, и когда объект инициирует указанное событие, будет выполнена указанная функция обратного вызова.
- DOMContentLoaded:
Когда начальный HTML-документ полностью загружен и анализируют, событие DomcontentLoade срабатывает без необходимости дождаться листа стиля, изображения и суб-кадров.
- GetBoundingClientRect:
Метод Element.getBoundingClientRect() возвращает размер элемента и его положение относительно окна просмотра.
- получить атрибут:
Метод getAttribute() возвращает значение атрибута с указанным именем атрибута.
-МДН
2.1.3 Специальные операции🖐️
1. Что я даюЗаметка одновременно добавляет атрибуты src и data-src.При загрузке веб-страницы будет загружаться изображение, установленное атрибутом src.В это время мы устанавливаем то же самое изображение, которое будет кэшировано позже, поэтому только требуется один запрос. Как показано ниже
2. Когда страница попадает в визуальную область, нам нужно загрузить картинки, которые действительно нужно отображать.
- 1. Отслеживайте загрузку страницы и получайте размер окна
Когда документ HTML полностью загружен и проанализирован, запускается событие DOMContentLoaded, и все изображения получаются через document.getElementsByTagName('img'), а также получается высота окна браузера.
document.addEventListener('DOMContentLoaded', () => {
imgs = document.getElementsByTagName('img'); // 取得所有图片
const viewHeight = window.innerHeight || docuemnt.documentElement.clientHeight; // JS 浏览器嗅探,兼容浏览器
}
- Слушайте события прокрутки
При этом срабатывает callback-функция lazyload, после чего функция судит, появилась ли картинка в окне, или уже появилась.
window.addEventListener('scroll',lazyload,false);
- Ленивая функция загрузки:
function lazyload() {
for (let i = 0;i < imgs.length;i++) {
let distance = viewHeight - imgs[i].getBoundingClientRect().top;
//当图片出现在视窗当中,或者之前已经出现了。
//将data-src属性的值赋给src属性,从而在页面上显示真正的图片
if (distance > 0) {
imgs[i].src = imgs[i].getAttribute('data-src');
}
}
}
Код: HTML:
<div class="container">
<div class="img"><img src="./loading.svg" data-src="https://img.36krcdn.com/20210122/v2_7d557e30f1254bdc8597f5eccdeb8e29_img_png?x-oss-process=image/resize,m_mfit,w_600,h_400,limit_0/crop,w_600,h_400,g_center" alt="加载中" class="pic"></div>
<div class="img"><img src="./loading.svg" data-src="https://img.36krcdn.com/20210122/v2_8327e6797c2745f99e8ecc6bae1958b4_img_png" alt="加载中" class="pic"></div>
<div class="img"><img src="./loading.svg" data-src="https://img.36krcdn.com/20210122/v2_6c513ab4937d456d9554deca27e9f5f0_img_000?x-oss-process=image/resize,m_mfit,w_600,h_400,limit_0/crop,w_600,h_400,g_center" alt="加载中" class="pic"></div>
<div class="img"><img src="./loading.svg" data-src="https://img.36krcdn.com/20210122/v2_2ef591c9986a47099c5905682fb6365f_img_png?x-oss-process=image/resize,m_mfit,w_600,h_400,limit_0/crop,w_600,h_400,g_center" alt="加载中" class="pic"></div>
<div class="img"><img src="./loading.svg" data-src="https://img.36krcdn.com/20210122/v2_f91f15ae0804422da41dce10a1ce37ad_img_jpg?x-oss-process=image/resize,m_mfit,w_600,h_400,limit_0/crop,w_600,h_400,g_center" alt="加载中" class="pic"></div>
<div class="img"><img src="./loading.svg" data-src="https://img.36krcdn.com/20210121/v2_73ef9df5c01c4210a01aa46b85b0fd8a_img_jpg" alt="加载中" class="pic"></div>
<div class="img"><img src="./loading.svg" data-src="https://img.36krcdn.com/20210122/v2_2ee8b63dde624520836e412e40251df5_img_000?x-oss-process=image/resize,m_mfit,w_600,h_400,limit_0/crop,w_600,h_400,g_center" alt="加载中" class="pic"></div>
<div class="img"><img src="./loading.svg" data-src="https://img.36krcdn.com/20210122/v2_d500f1a71d9d414c9cd631f138f5f769_img_png" alt="加载中" class="pic"></div>
<div class="img"><img src="./loading.svg" data-src="https://img.36krcdn.com/20210122/v2_3789126b279e4889ae75988a7523c57b_img_000?x-oss-process=image/resize,m_mfit,w_600,h_400,limit_0/crop,w_600,h_400,g_center" alt="加载中" class="pic"></div>
<div class="img"><img src="./loading.svg" data-src="https://img.36krcdn.com/20210122/v2_d4fac7849276424f89522946e8ffb128_img_000?x-oss-process=image/resize,m_mfit,w_600,h_400,limit_0/crop,w_600,h_400,g_center" alt="加载中" class="pic"></div>
</div>
</body>
css:
<style>
* {
margin: 0;
padding: 0;
}
.container {
width: 1200px;
margin: 0 auto;
}
.img {
width: 500px;
height: 500px;
}
</style>
js:
<script>
let imgs;
document.addEventListener('DOMContentLoaded', () => {
imgs = document.getElementsByTagName('img'); // 把所有的图片抓住
const viewHeight = window.innerHeight || docuemnt.documentElement.clientHeight; // JS 浏览器嗅探
console.log(viewHeight)
function lazyload() {
for (let i = 0;i < imgs.length;i++) {
let distance = viewHeight - imgs[i].getBoundingClientRect().top;
if (distance > 0) {
imgs[i].src = imgs[i].getAttribute('data-src');
}
}
}
window.addEventListener('scroll',lazyload,false);
},false)
</script>
увидеть эффект
2.1.4 Улучшение❣️
Здесь написан код, и мы вроде бы реализовали ленивую загрузку, когда страница начинает загружаться, все картинки не загружаются, но сначала определяем, прокручивается ли картинка до окна, чтобы загрузить картинку.
Однако мы прослушиваем событие прокрутки, и срабатывает только прокрутка.
Итак, на основе приведенного выше кода добавим загрузку вверху страницы:
window.addEventListener('load',lazyload,false);
Как только страница загружена, он автоматически выполняет ее загрузку.
Но на самом деле есть еще недостаток. Когда мы прокручиваем, события запускаются очень часто, что вызывает проблемы с производительностью и требует оптимизации.
Переходим к нашей следующей теме:节流
2.2 Дросселирование
2.2.1 Концепция 🧐
События с высокой частотой запускаются, но будут выполняться только один раз в n секунд, регулирование уменьшит частоту выполнения функции. Когда вышеуказанное событие прокрутки запускается несколько раз, нам нужно использовать метод регулирования, чтобы уменьшить количество выполнений функций.
Мы можем видеть, что когда мы прокручиваем мышь,lazyload()
Исполнение: просто прокрутка вызовет так много событий
2.2.2 Реализовать упрощенную версию дросселирования 😲
будет выполняться только один раз в n секунд
- Когда мы слушаем событие прокрутки, вызывается функция дросселя, и два параметра
Первоначальная функция отложенной загрузки становится функцией обратного вызова, и время 100 мс
window.addEventListener('scroll',throttle(lazyload,1000),false);
- В функции дроссельной заслонки установите и выполните fn один раз в течение интервала времени, сохранив количество выполнений.
const throttle = (fn,interval) => {
let last = 0;//上一次触发回调的时间
return function () {
let now = +new Date();
if(now - last >= interval){
last = now
fn();
}
}
}
Даже если он скользит вниз, он запускает функцию ленивой загрузки только 9 раз.
Более совершенный троттлинг можно увидеть здесь
2.3 Карта спрайтов
Спрайты используются на веб-сайтах, где используется множество маленьких значков. Вместо того, чтобы ссылаться на каждую маленькую иконку на странице в виде файла .png, использование Sprite требует ссылки только на одно изображение.
Следующее изображение представляет собой перехват изображения Sprite, используемого на официальном сайте Jingdong:
Таким образом, мы можем объединить множество запросов изображений в одно изображение, эффективно сокращая HTTP-запросы. В сочетании с атрибутом background-position изображения в css будет отображаться требуемое изображение. Вот введение в свойство background-position: background-position: Установите начальную позицию фонового изображения.
Получите значок в правом нижнем углу:
{
background-image:url('https://iknow- pic.cdn.bcebos.com/faedab64034f78f0cbe417637b310a55b2191cb6?x-bce- process=image/resize,m_lfit,w_600,h_800,limit_1');
background-repeat:no-repeat;
background-attachment:fixed;
background-position: -340px -255px;
}
2.4 Кодирование изображения Base64
Base64 — это формат кодирования. По сравнению с отложенной загрузкой этот метод не требует прямого запроса.
Однако у него есть ограничения:针对尺寸很小的图标
, и его нельзя комбинировать с другими изображениями для синтеза изображения спрайта. Рекомендуется использовать его в виде кодировки Base64. В конце концов, это может уменьшить накладные расходы HTTP-запроса.
2.5 формат изображения webp
Видно, что размер изображения значительно уменьшился.
Изображения в этом формате: подходят для больших изображений, особенно изображений заголовков, изображений баннеров и изображений на страницах сведений о продукте, могут использовать формат webp, который может быть уменьшен на 25% в размере, и в то же время четкость не повреждается. Таким образом, в сочетании с нашей предыдущей ленивой загрузкой была достигнута определенная оптимизация количества http-запросов и размера изображения.
2.5.1 webp-конвертер😁
Используйте инструменты для оптимизации производительности изображения
- первое использование
npm i webp-converter
Установить - Я нашел изображение в формате .jpg в Интернете, размер изображения составляет 16,7 КБ (17 194 байта).
`
- Создать index.js
const webp = require('webp-converter');
webp.cwebp("1.jpg","output.webp","-q 80%",function(status,error) {
console.log(status);
})
Введите webp-конвертер, оптимизируйте изображение формата jpg с именем 1 в изображение 80% webp и назовите результат output.webp, очевидно, размер сильно уменьшится.
Суммировать
О методе оптимизации загрузки изображений было представлено ранее, что его можно оптимизировать, уменьшив количество http-запросов и уменьшив размер изображения.
-
Уменьшите количество http-запросов: 1. lazyload ленивая загрузка (throttle оптимизирует дросселирование процесса ленивой загрузки)
2. Кодировка изображения Base64
3. Спрайт
-
уменьшить размер изображения
1. Используйте формат webp
Затем, когда они используются вместе, производительность может быть улучшена, например, формат webp + отложенная загрузка и т. д.
На этот раз статья по оптимизации производительности, посвященная загрузке изображений из внешнего интерфейса, здесь первой. В статье может быть много недостатков или несовершенств. Пожалуйста, также отразите ваши предложения в области комментариев большого парня, и я постараюсь это изменить. 💦💦💦
文章有一丢丢长,码字时间也有一丢丢长。如果可以的话,厚个脸皮求个赞。🙈🙈🙈
Хорошо, поехали сегодня ❤️