Привет, спасибо за видео, насчёт первого пункта не согласен. Ты скорее всего взял изображение пнг для сравнение без сжатия, пнг намного лучше как мне кажется сжимается, и при сжатии пнг размер у него все же меньше чем у вебп. Для сжатия пнг юзаю tinyjpg, как и говорил ранее размер все же меньше чем при сжатии webp
Так я изначально и webp взял без сжатия. По поводу того, что из них лучше сжимается, проверю чуть позже. Но обычно вебп всегда сжималось лучше. В общем, потестирую чуть позже :)
тут зависит от картинки. Логотипы, какие-то текста и там где нет градиента или фото (условно векторное что-то), то лучше конечно PNG . А вот фото, гредиенты тому подобное лучше в webp
Смотрю ваш канал уже несколько дней, по плейлистам с нуля научился верстать макет практически любой сложности, сейчас почти изучил основы js. Дай бог вам здоровья за ваш труд. Нет слов описать благодарность, я очень вами восхищен)
функциональное программирование даунгрейдить в императивное для оптимизации - это зачет. ещё можно в машинных кодах кодить, там выигрыш будет ещё больше.
спасибо большое, подписался. конечно я на некстжс работаю в данный момент и там много уже оптимизаций из коробки но всё равно полезный обзор, ещё я подключал библиотеку react-intersection-observer которая при попадании элемента в окно браузера подгружает DOM элемент. так же благодаря ей удобно динамически подгружать на клиенстких компонентах данные с сервера при попадании в область видимости.
Спасибо за интересное видео! 👍 Насчёт 11-го пункта не согласен. Цикл for...in является крайне медленным и трудно оптимизируемым. Руководство по написанию JS-кода Google JavaScript Style Guide (пункт 5.8.1) рекомендует по возможности отдавать предпочтение другим альтернативным способам обхода по собственным перечисляемым свойствам объекта. Блок "через for" некорректен для оценки перформанса, поскольку ничего не делает (является по сути "мёртвым кодом"). При корректном сравнении преимущество будет отнюдь не на стороне for...in.
23:43 - насколько это разумно, учитывая, что хттп запросы обычно и так сжимаются через гзип и пр алгоритмы? Повторяющиеся ключи в объектах будут подменятся на фразы из словаря компрессора, в из-за чего выигрыш в сокращении этих слов будет сомнителен
Ну, сами данные, насколько я знаю, он не сжимает. Потому что их потом нужно разжать. Написал простенький сервер для тестов на ноде. Тут я получаю json и сжимаю через gzip. Если в jsonData подставить json: const jsonData = JSON.stringify(json); То на выходе я скачал 4кб данных. Если подставить newJson: const jsonData = JSON.stringify(newJson); То будет 3.9кб. Разница всего в 1кб, но это потому что json маленький. _____ P.S. Я надеюсь, что вы именно это имели ввиду. Код для тестов: import express from 'express'; import zlib from 'zlib'; const app = express(); const url = 'jsonplaceholder.typicode.com/todos'; app.get('/', (req, res) => { fetch(url) .then(response => response.json()) .then(json => { const newJson = json.map((data) => ({ uI: data.userId, i: data.id, t: data.title, c: data.completed })); const jsonData = JSON.stringify(newJson); const gzip = zlib.createGzip(); res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Encoding', 'gzip'); res.writeHead(200); gzip.pipe(res); gzip.write(jsonData); gzip.end(); }) }); app.listen(3000);
про асинк и дефер ты упустил самое главное. дело не в том как они блокируют страницу, а порядок их выполнения. если есть несколько скриптов при асинке - выполяняются в разнобой, кто первый загрузился - тот и выполнился. при дефер - там порядок следования сохраняется при загрузке. т.е. если один скрипт зависит от работы другого - то при асинке может все сломаться т.к. 2-й может загрузится и выполнится вначале. При дефер такого не произойдет, по этому он чаще и используется. А не потому что он там что-то блокирует или нет.
Не упомянул чанкинг node modules. Популярные сборщики имеют функцию подключения npm пакетов только на тех страницах, где они используются в js. Использовал эту фичу в работе, на больших проектах сильно ускоряет загрузку страниц
Очень круто, конечно, но, если я правильно понял, мы сжимаем все, но при этом используем библиотеки, которые имеют вес. Оптимизации не видно, в конечном счете
Библиотеки хоть и имеют вес, но совсем небольшой. А вот пользы приносят намного больше. Давай посчитаем Библиотека knip не попадает в финальный билд. Ее вес не учитываем. ReactVirtualized - 30 килобайт cdn.jsdelivr.net/npm/react-virtualized@9.22.5/dist/umd/react-virtualized.min.js Весит хоть и много, но тут уже сам смотри, что важнее. Скачать 30 килобайт, либо отрисовывать кучу элементов в дом дереве. Плюс эта куча элементов может отрисовываться в разных местах, а библиотеку можно скачать один раз и даже попросить браузер ее закэшировать MessagePack - 9 килобайт cdn.jsdelivr.net/npm/@msgpack/msgpack@3.0.0-beta2/dist.es5+umd/msgpack.min.js Если мы данных по сети гоняем больше, чем на 9 килобайт, то имеет смысл ее подключить. React Lottie - 2 килобайта cdn.jsdelivr.net/npm/react-lottie@1.2.4/dist/index.min.js Библиотека для debounce / throttle по идее вообще не нужна. Это две простые функции на 10 строк кода, которые можно вручную реализовать Ну и вроде все по библиотекам :)
@@kakieToYroki все зависит от задачи и времени на ее исполнение. Я не думаю, что для стартапа/продукта ты будешь писать свою виртуализацию или для оптимизации писать messagePack. Умение правильно выставлять приоритеты - ключ к успеху!
На новой работе встретился с тем, что линтер ругается на for in, hasOwnProperty , приходится какие-то окольные методы использовать) А это оказывается быстрее
Линтер, возможно, ругается из-за нарушения правила `eslint: no-prototype-builtins`, согласно которому метод hasOwnProperty не рекомендуется вызывать на самом объекте. Во-первых, это небезопасно, так как свойство может быть переопределено у объекта. Во-вторых, прототипом объекта может быть не Object, а null. Например, при создании объекта через Object.create(null) или Object.groupBy(arr, func) этот метод в нём попросту будет отсутствовать. Поэтому, в Airbnb JavaScript Style Guide (пункт 3.7) рекомендуется вызывать данный метод у прототипа: Object.prototype.hasOwnProperty.call(obj, key). К тому же в Google JavaScript Style Guide (пункт 5.3.3) не рекомендуется использовать hasOwnProperty при "structs"-форме объектного литерала. А вместо цикла for...in с методом hasOwnProperty предлагается по возможности отдавать предпочтение более эффективным способам обхода объекта: for...of (для итерируемых объектов) или Object.keys/Object.values/Object.entries (пункт 5.8.1).
@@kakieToYroki В блоке "через for" на видео (12:09) у нас идёт обход по перечисляемым (enumerable) свойствам пустого массива и его цепочки прототипов. Учитывая, что ни пустой массив items, ни Array, ни Object не содержат перечисляемых свойств, то цикл for...in не совершит ни единой итерации. Чтобы сделать блок "через for" эквивалентным блоку "через map", нужно переписать первый блок примерно так: const items = []; for (const key in myObject) { const has = Object.prototype.hasOwnProperty; if (!has.call(myObject, key)) continue; const value = myObject[key]; items.push(value.item); } Примечательно, что два обхода (Object.values и метод map) вдруг окажутся заметно шустрее одного обхода с медлительным for...in. 🧐
Я попробовал библиотечку knip но она почему-то выдала мне целую кучу Unused exports (62) которые на самом деле используются в других файлах через import. Не могу понять почему так происходит. Вот например: AUTO_POSTING_PERIODS_ARRAY unknown src/common/constants.js:114:14 Идем на 114 строку файлика src/common/constants.js и видим там следующее: export const AUTO_POSTING_PERIODS_ARRAY = [ { value: 'PREVIOUS', name: 'Past' }, { value: 'NEXT', name: 'Next' }, ];
Возможно у вас несколько точек входа в приложение. В моем случае у меня был только файл main.jsx. Но на реальных проектах бывают всякие утилиты, которые запускаются отдельно. У них своя точка входа, независящая от основного приложения. Плюс, возможно, он ругается из-за того, что вы написали export, но нигде не написали import. Если вы эту константу используете только в этом файле, то уберите export
9 сортировка, не совсем правильная оценка как мне кажется, и результат, в первом "неоптимальном случае" мы сортируем массив значений, что бы в нем небыло, и его же на выходе получаем отсортированный, а в "оптимизированном" варианте, сортируются числа, и на выходе массив чисел а не строковых дат, к примеру.в таком случае актуальнее сортировать структуры с оригинаьным значением и промапленным, однако такие варианты тяжелее для восприятия в рамках одной минуты )
Понятия не имею, откуда вы взяли эти цифры. Вот либа из видео, она весит 53кб cdnjs.cloudflare.com/ajax/libs/lottie-web/5.7.3/lottie.min.js Вот версия для реакта, которую я показывал в видео. Весит 2кб cdn.jsdelivr.net/npm/react-lottie@1.2.4/dist/index.min.js Плюс нужно помнить, что на сайте может быть не одна, а N гифок. Поэтому нужно иметь свою голову на плечах и посчитать все данные, перед тем как грузить либу. У вас может быть одна маленькая гифка на весь сайт. Вы можете ее сжать и получить размер даже меньше lottie библиотеки. Разумеется, в таком кейсе нет смысла целую либу грузить
Уже писал этот комментарий, но повторюсь: Вот либа из видео, она весит 53кб cdnjs.cloudflare.com/ajax/libs/lottie-web/5.7.3/lottie.min.js Вот версия для реакта, которую я показывал в видео. Весит 2кб cdn.jsdelivr.net/npm/react-lottie@1.2.4/dist/index.min.js Плюс нужно помнить, что на сайте может быть не одна, а N гифок Также и наоборот, у вас может быть одна маленькая гифка на весь сайт. Вы можете ее сжать и получить размер даже меньше lottie библиотеки. Разумеется, в таком кейсе нет смысла целую либу грузить
Привет, спасибо за видео, насчёт первого пункта не согласен. Ты скорее всего взял изображение пнг для сравнение без сжатия, пнг намного лучше как мне кажется сжимается, и при сжатии пнг размер у него все же меньше чем у вебп. Для сжатия пнг юзаю tinyjpg, как и говорил ранее размер все же меньше чем при сжатии webp
Так я изначально и webp взял без сжатия. По поводу того, что из них лучше сжимается, проверю чуть позже. Но обычно вебп всегда сжималось лучше. В общем, потестирую чуть позже :)
Потестировал и да, во многих ситуациях png, действительно, сжимается намного лучше. Спасибо за комментарий
тут зависит от картинки. Логотипы, какие-то текста и там где нет градиента или фото (условно векторное что-то), то лучше конечно PNG . А вот фото, гредиенты тому подобное лучше в webp
Слышал также юзаются avif форматы, они еще меньше, чем webp
Смотрю ваш канал уже несколько дней, по плейлистам с нуля научился верстать макет практически любой сложности, сейчас почти изучил основы js. Дай бог вам здоровья за ваш труд. Нет слов описать благодарность, я очень вами восхищен)
Супер! Пересмотрю и законспектирую. Бесценно!
Не первый год во Frontend - отлично структурированное и информативное видео
А то обычно когда спрашиваешь про оптимизации, то слышишь про хуки реакт )
Пожалуй, самый полезный контент за последнее время!
Продолжай в том же духе! Комьюнити будет тебе благодарно)
Тут даже и не для новичков много полезного, лайк однозначно
и полного бреда
@@gabblz480 почему бреда?
Не новичок но спасибо за систематизацию , лайк однозначно
самое лучшее что я видел про способы оптимизаций. однозначный лайк видосу
функциональное программирование даунгрейдить в императивное для оптимизации - это зачет. ещё можно в машинных кодах кодить, там выигрыш будет ещё больше.
Bro, до последнего не хотел лайк ставить, не удержался, ЛАЙК ❤❤❤
Удивительное качество контента! Спасибо
Не зря я подписан)) очень очень круто и интересно.
Мы всё знали, но ТЫ - красавчик!!!🤗
Получается ты красавчик, раз все знал :)
@@kakieToYroki 😁
Пожалуй, это самый настоящий клад) премного благодарен за великолепный контент!
Вау! Это видео просто находка! Много ценных мыслей, спасибо!
Благодарю за видео,позновательно !
спасибо большое, подписался. конечно я на некстжс работаю в данный момент и там много уже оптимизаций из коробки но всё равно полезный обзор, ещё я подключал библиотеку react-intersection-observer которая при попадании элемента в окно браузера подгружает DOM элемент. так же благодаря ей удобно динамически подгружать на клиенстких компонентах данные с сервера при попадании в область видимости.
Классный контент. У этого канала большое будущее ;)
🩷
Супер, просто и полезно в копилку.
Оч годно)
Спасибо 🙏🏻
Супер! Очень полезная инфа, особенно про ресурсоемкость функций и их методов))
Супер контент, огромное спасибо!
Великолепное видео! Спасибо большое!!!!!
Это общие оптимизации, хотелось пройтись на примере, по показателям того же lighthouse, и увидеть какие показатели можно поправить в лучшую сторону.
Отличное видео, спасибо за контент!
Спасибо , полезно !
Топ инфа, спасибо! Можно побольше вот такого пожалуйста?
Lighthouse работает и с локальном сервером.
Да, действительно, давно его на локалхосте не тестировал. Закреплю ваш комментарий, весьма полезный
И показывает показатели относительно мощности локального компьютера, что для большинства пользователей не правда.
@aazubakin там не только циферки быстродействия нужно смотреть. Там можно увидеть и другую полезную информацию
Поэтому, используйте google speed
Большое спасибо, узнал много полезного
сокровище, а не видео
очень много полезного для себя увидел - спасибо
Спасибо за интересное видео! 👍 Насчёт 11-го пункта не согласен. Цикл for...in является крайне медленным и трудно оптимизируемым. Руководство по написанию JS-кода Google JavaScript Style Guide (пункт 5.8.1) рекомендует по возможности отдавать предпочтение другим альтернативным способам обхода по собственным перечисляемым свойствам объекта.
Блок "через for" некорректен для оценки перформанса, поскольку ничего не делает (является по сути "мёртвым кодом"). При корректном сравнении преимущество будет отнюдь не на стороне for...in.
Хмм… потестирую этот момент, спасибо
Можно подробнее о правильной загрузке шрифтов чтобы текст в сайте не прыгал
Топ контент!
23:43 - насколько это разумно, учитывая, что хттп запросы обычно и так сжимаются через гзип и пр алгоритмы? Повторяющиеся ключи в объектах будут подменятся на фразы из словаря компрессора, в из-за чего выигрыш в сокращении этих слов будет сомнителен
Ну, сами данные, насколько я знаю, он не сжимает. Потому что их потом нужно разжать. Написал простенький сервер для тестов на ноде. Тут я получаю json и сжимаю через gzip. Если в jsonData подставить json:
const jsonData = JSON.stringify(json);
То на выходе я скачал 4кб данных.
Если подставить newJson:
const jsonData = JSON.stringify(newJson);
То будет 3.9кб. Разница всего в 1кб, но это потому что json маленький.
_____ P.S.
Я надеюсь, что вы именно это имели ввиду. Код для тестов:
import express from 'express';
import zlib from 'zlib';
const app = express();
const url = 'jsonplaceholder.typicode.com/todos';
app.get('/', (req, res) => {
fetch(url)
.then(response => response.json())
.then(json => {
const newJson = json.map((data) => ({ uI: data.userId, i: data.id, t: data.title, c: data.completed }));
const jsonData = JSON.stringify(newJson);
const gzip = zlib.createGzip();
res.setHeader('Content-Type', 'application/json');
res.setHeader('Content-Encoding', 'gzip');
res.writeHead(200);
gzip.pipe(res);
gzip.write(jsonData);
gzip.end();
})
});
app.listen(3000);
про асинк и дефер ты упустил самое главное. дело не в том как они блокируют страницу, а порядок их выполнения. если есть несколько скриптов при асинке - выполяняются в разнобой, кто первый загрузился - тот и выполнился. при дефер - там порядок следования сохраняется при загрузке. т.е. если один скрипт зависит от работы другого - то при асинке может все сломаться т.к. 2-й может загрузится и выполнится вначале. При дефер такого не произойдет, по этому он чаще и используется. А не потому что он там что-то блокирует или нет.
Да, хорошее замечание. Спасибо
Можно добавить пагинацию чтобы грузить данные с бэка порциями
Тебе друг, тебе Мурыч ответил , посвятив целый стрим! As for js
спасибо очень круто и интересно
Пункт 6. с каких пор img блочит показ страницы? если только займет поток при http1. lazy loading это костыль и для другого
Бро подскажи какая у тебя тема для vs code ? Контент топ !
какая-то стандартная, я vs code только для видео использую, поэтому никакие настройки не менял :)
Еще можно было б и вебсокеты упомянуть , что бы не нагружать сервер лишними соединениями
вебсокеты - и есть лишние соединения)
Не упомянул чанкинг node modules. Популярные сборщики имеют функцию подключения npm пакетов только на тех страницах, где они используются в js. Использовал эту фичу в работе, на больших проектах сильно ускоряет загрузку страниц
привет можно поподробнее пожалуйста
С webp надо быть осторожным с фотографиями с высокой растеризация изображения, например, где присутствует небо. Очень заметно ухудшение качества!
Автор видео: мы сэкономили 2 килобайта!! Я: ну если поставить сюда эти картинки по 2МБ каждая, то будет норм
ахаххааха кайф )
кстати хотелось бы то же самое но для nextjs увидеть
Очень круто, конечно, но, если я правильно понял, мы сжимаем все, но при этом используем библиотеки, которые имеют вес. Оптимизации не видно, в конечном счете
Библиотеки хоть и имеют вес, но совсем небольшой. А вот пользы приносят намного больше. Давай посчитаем
Библиотека knip не попадает в финальный билд. Ее вес не учитываем.
ReactVirtualized - 30 килобайт
cdn.jsdelivr.net/npm/react-virtualized@9.22.5/dist/umd/react-virtualized.min.js
Весит хоть и много, но тут уже сам смотри, что важнее. Скачать 30 килобайт, либо отрисовывать кучу элементов в дом дереве. Плюс эта куча элементов может отрисовываться в разных местах, а библиотеку можно скачать один раз и даже попросить браузер ее закэшировать
MessagePack - 9 килобайт
cdn.jsdelivr.net/npm/@msgpack/msgpack@3.0.0-beta2/dist.es5+umd/msgpack.min.js
Если мы данных по сети гоняем больше, чем на 9 килобайт, то имеет смысл ее подключить.
React Lottie - 2 килобайта
cdn.jsdelivr.net/npm/react-lottie@1.2.4/dist/index.min.js
Библиотека для debounce / throttle по идее вообще не нужна. Это две простые функции на 10 строк кода, которые можно вручную реализовать
Ну и вроде все по библиотекам :)
@@kakieToYroki все зависит от задачи и времени на ее исполнение. Я не думаю, что для стартапа/продукта ты будешь писать свою виртуализацию или для оптимизации писать messagePack. Умение правильно выставлять приоритеты - ключ к успеху!
На новой работе встретился с тем, что линтер ругается на for in, hasOwnProperty , приходится какие-то окольные методы использовать) А это оказывается быстрее
На твоей работе не любят производительность )
Линтер, возможно, ругается из-за нарушения правила `eslint: no-prototype-builtins`, согласно которому метод hasOwnProperty не рекомендуется вызывать на самом объекте. Во-первых, это небезопасно, так как свойство может быть переопределено у объекта. Во-вторых, прототипом объекта может быть не Object, а null. Например, при создании объекта через Object.create(null) или Object.groupBy(arr, func) этот метод в нём попросту будет отсутствовать. Поэтому, в Airbnb JavaScript Style Guide (пункт 3.7) рекомендуется вызывать данный метод у прототипа: Object.prototype.hasOwnProperty.call(obj, key).
К тому же в Google JavaScript Style Guide (пункт 5.3.3) не рекомендуется использовать hasOwnProperty при "structs"-форме объектного литерала. А вместо цикла for...in с методом hasOwnProperty предлагается по возможности отдавать предпочтение более эффективным способам обхода объекта: for...of (для итерируемых объектов) или Object.keys/Object.values/Object.entries (пункт 5.8.1).
@@kakieToYroki В блоке "через for" на видео (12:09) у нас идёт обход по перечисляемым (enumerable) свойствам пустого массива и его цепочки прототипов. Учитывая, что ни пустой массив items, ни Array, ни Object не содержат перечисляемых свойств, то цикл for...in не совершит ни единой итерации.
Чтобы сделать блок "через for" эквивалентным блоку "через map", нужно переписать первый блок примерно так:
const items = [];
for (const key in myObject) {
const has = Object.prototype.hasOwnProperty;
if (!has.call(myObject, key)) continue;
const value = myObject[key];
items.push(value.item);
}
Примечательно, что два обхода (Object.values и метод map) вдруг окажутся заметно шустрее одного обхода с медлительным for...in. 🧐
Слушай, а если линтер настроен и выдает переменные которые не используются, получается knip не нужен ? Или он глубже копает чем линтер ?
knip может показывать целиком неиспользуемые файлы, а не только переменные
Плюс он вроде зависимости из package.json проверяет
Я попробовал библиотечку knip но она почему-то выдала мне целую кучу Unused exports (62) которые на самом деле используются в других файлах через import. Не могу понять почему так происходит.
Вот например: AUTO_POSTING_PERIODS_ARRAY unknown src/common/constants.js:114:14
Идем на 114 строку файлика src/common/constants.js и видим там следующее:
export const AUTO_POSTING_PERIODS_ARRAY = [
{ value: 'PREVIOUS', name: 'Past' },
{ value: 'NEXT', name: 'Next' },
];
Возможно у вас несколько точек входа в приложение. В моем случае у меня был только файл main.jsx. Но на реальных проектах бывают всякие утилиты, которые запускаются отдельно. У них своя точка входа, независящая от основного приложения.
Плюс, возможно, он ругается из-за того, что вы написали export, но нигде не написали import. Если вы эту константу используете только в этом файле, то уберите export
9 сортировка, не совсем правильная оценка как мне кажется, и результат, в первом "неоптимальном случае" мы сортируем массив значений, что бы в нем небыло, и его же на выходе получаем отсортированный, а в "оптимизированном" варианте, сортируются числа, и на выходе массив чисел а не строковых дат, к примеру.в таком случае актуальнее сортировать структуры с оригинаьным значением и промапленным, однако такие варианты тяжелее для восприятия в рамках одной минуты )
Гифка весит 100-200кб а либа для lottie 800.
Вот это оптимизатор
Понятия не имею, откуда вы взяли эти цифры. Вот либа из видео, она весит 53кб
cdnjs.cloudflare.com/ajax/libs/lottie-web/5.7.3/lottie.min.js
Вот версия для реакта, которую я показывал в видео. Весит 2кб
cdn.jsdelivr.net/npm/react-lottie@1.2.4/dist/index.min.js
Плюс нужно помнить, что на сайте может быть не одна, а N гифок. Поэтому нужно иметь свою голову на плечах и посчитать все данные, перед тем как грузить либу.
У вас может быть одна маленькая гифка на весь сайт. Вы можете ее сжать и получить размер даже меньше lottie библиотеки. Разумеется, в таком кейсе нет смысла целую либу грузить
У меня на проекте svg по 500кБ есть, я плачу после этого видео 😅
У вас канал на рутубе?? Боль:(
Первый
🥇выиграл золотую медаль :)
@@kakieToYroki ура
Пишу комент о том что есть еще SSR, как вы и просили в конце видео)))
(
Этот вариант очень спорный и зависит от случая
Второй,где серебро😂?
🥉Судя по количеству комментов, ты уже третий :)
@@kakieToYroki медную медаль плиз
@@R_y_k_u_s 🥉 держи )
Только сам лотти весит тонну
Уже писал этот комментарий, но повторюсь:
Вот либа из видео, она весит 53кб
cdnjs.cloudflare.com/ajax/libs/lottie-web/5.7.3/lottie.min.js
Вот версия для реакта, которую я показывал в видео. Весит 2кб
cdn.jsdelivr.net/npm/react-lottie@1.2.4/dist/index.min.js
Плюс нужно помнить, что на сайте может быть не одна, а N гифок
Также и наоборот, у вас может быть одна маленькая гифка на весь сайт. Вы можете ее сжать и получить размер даже меньше lottie библиотеки. Разумеется, в таком кейсе нет смысла целую либу грузить
Lottie?! 😂 Не... Ну слабенько же...
Оптимизация это мое слабое место
Очень полезное видео! Спасибо!