Как стать автором
Обновить
2
Карма
0
Рейтинг
Бобров Максим Юрьевич @demimurych

Тех SEO аудит. LightHouse WebVitals PageSpeed

  • Подписчики 19
  • Подписки 1

JavaScript: заметка о requestAnimationFrame и requestIdleCallback

Строго говоря, событие raf нужно использовать всегда, когда Вы собираетесь вносить изменения в DOM. Чем Вы гарантируете себе ситуацию, когда не вызовете лишних Reflow. И при этом будучи абсолютно уверенным в том, что ваши изменения отобразятся ровно так скоро как это возможно.

tramsform насколько я помню не приводит к reflow. Но я могу и забыть. Всегда нужно контролировать себя через тот же DevTools вкладка Perfomance, записать trace. Там есть отдельный таймлайн для процессов с layout. Вот тут https://developers.google.com/web/fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing инструкция с картинками

JavaScript: заметка о requestAnimationFrame и requestIdleCallback

Заметке не хватает очень важных акцентов, ради которых эта заметка и должна была бы писаться. Более того, из последующих примеров видно, что автор не до конца прочувствовал что для чего и как работает.

requestAnimationFrame

основная задача requestAnimationFrame заключается не в том, чтобы Вы писали с его помощью анимации. Это следствие. Его основная задача, предоставить программисту сигнал, когда он может, без боязни просадить производительность, работать с DOM.

Дело в том, что даже чтение некоторых свойств DOM дерева может приводит к полной перерисовке макета в окне браузера. Что, как мы понимаем, является ОЧЕНЬ дорогой операцией.

Я хочу подчеркнуть - даже чтение некоторых свойств DOM. Еще раз. Не модификации DOM. А чтении.

Для наиболее любознательных рекомендую гуглить DOM Reflow. Или начать с этой ссылки https://gist.github.com/paulirish/5d52fb081b3570c81e3a где популярно разбирается этот процесс, и причины, которые приводят к серьезным потерям производительности.

Так вот именно requestAnimationFrame является той волшебной палочкой, которая дает нам отмашку, когда мы безбоязненно можем вертеть нашим DOM как нам хочется.

requestIdleCallback

Предоставляет на много больше чем то о чем Вы написали. И, что самое главное, при правильной организации нашего кода, время, предоставляемое для callback может измерятся десятками миллисекунд.

Изменять DOM внутри этого callback нельзя не по той причине, что нам выдали слишком мало времени. А по той причине, что requestIdleCallback может сработать в любой момент времени. Даже тогда, когда наша неаккуратная работа с DOM может привести к постоянным Reflow. И именно по этой причине в этом апи не рекомендуется работать с DOM, если, конечно, вы не понимаете что делаете. А рекомендуется организовывать очередь, для следующего срабатывания requestAnimationFrame

Safari

И автор совершенно прав. Safari это IE современности. Я очень не завидую проектам, которые обязаны его поддерживать. Потому как этот браузер не просто IE современного мира, он значительно хуже. Так как мейнтенеры, не просто отказывают в поддержке большого количества таких вкусных вещей, но и не дают им никаких альтернатив, возвращая нас во время 2000 годов, с хаками вида setTimeout( func, 0);

Хочу поиск как у MDN

это все прекрасно, только бесполезно чуть более чем полностью, по той простой причине, что адекватность запросу, выдаваемой информации, стремиться к нулю. Как следствие все равно пользуешься поиском от корпорации бобра.

интересно, когда на mdn найдут ресурс починить сломаные к чертям локализации переводов?

или вернут виджет выбора языка на свое место. А то люди уже устали придумывать версии, накой черт его перенесли вниз страницы

35 вопросов с собеседования JavaScript-разработчика

Что такое SPA и как сделать его SEO-friendly?

И когда это вдруг SPA перестало быть SEO-friendly? Наверное тогда, когда кто-то решил что SPA это обязательно client-side rendering.

Удивительно что люди не знают о том, что первые SPA делались даже в ИЕ6, то есть где то в 2002 году. А полностью полноценными они стали с появлением возможности изменять state в History APi. Кажется в 2010 году. 

 

Объясните разницу между изменяемыми и неизменяемыми значениями

Значения примитивных типов (например, строка или число) не могут быть изменены после того, как попали в память.

В JavaScript нет примитивных типов и никогда не было. Глава 6 ECMA Spec.

 Всегда было любопытно, откуда возник этот странный миф о примитивных и ссылочных типах, и почему он до сих пор занимает чуть ли не первое место в умах JS разработчиков. 

Возможно потому, что никто из них не любит читать спецификацию языка, на котором пишет.

 

Значения объектных типов (объекты, массивы) могут изменяться в ходе работы программы.

Все типы в JS работают абсолютно одинаково. Никакой разницы в том, каким образом происходит работа с данными в обьекте или в строке - нет. И там и там данные имутабельны. 

 

В чем разница между let, const и var?

var объявляет переменную, которая может быть переопределена

Под словом переопределенная видимо подразумевается то, что можно опять писать var. 

Любопытно то, что на уровне bytecode ignition, конструкции типа

var a='str1';
var a='str2';
let b='str3'
b ='str4'

приведут к генерации абсолютно идентичного кода.

  221 S> 0x27c9c7b0c952 @   12 : 12 02             LdaConstant [2]
         0x27c9c7b0c954 @   14 : 26 f9             Star r2
  237 S> 0x27c9c7b0c956 @   16 : 12 03             LdaConstant [3]
         0x27c9c7b0c958 @   18 : 26 f9             Star r2
  253 S> 0x27c9c7b0c95a @   20 : 12 04             LdaConstant [4]
         0x27c9c7b0c95c @   22 : 26 f8             Star r3
  260 S> 0x27c9c7b0c95e @   24 : 12 05             LdaConstant [5]
         0x27c9c7b0c960 @   26 : 26 f8             Star r3

Иными словами, сакральное знание о переопределении бесполезно чуть более чем полностью. 

Так же любопытно, почему о бесполезном переопределении так много написано, а о том, что обязан знать каждый JS разработчик использующий let или const - то есть о TDZ ни слова.

В JS-функциях «побеждает» последний оператор return

По двум простым причинам:

1) В статье прямо сказано что "promise", то есть тот который был задан во время создания ( название переменной).

const promise = Promise.resolve('one'); 

Если предположить что автор ошибся и забыл поставить заглавную букву, то есть имея ввиду не ссылку promise которую он обьявил выше, а Promise вообще как класс то причина номер два, описанная в мое посте:

2) обьявляя async function он передал в finaly не функцию, а новый обьект Promise, который согласно спецификации как и любое другое значение отличное от функции оборачивается в () => переданной значение.

которое в случае примера из статьи равно созданному промису для функции, но не вызову функции.

то есть его код для наглядности можно переписать вот так

const testFuncPromise =  new Promise ( 
  (res, rej) => {     
    setTimeout( {console.log("Finaly"); res(); } , 2000)
  });

promise.finally( () => testFuncPromise );

То есть как только он написал в своем коде async () => { // come code } он передал в finaly не функцию () => { // come code }, которая выполниться в нужный момент, но новый промис, который был автоматически завернут в новую созданную автоматически функцию () => { return (Promise созданный при объявлении async) }

В JS-функциях «побеждает» последний оператор return

Пример жуткой безграмотности. А jake archibald несмотря на то что выступает как Google Developer Advocate уже не первый раз замечен в том, что несет ахинею.

Война return

Достаточно открыть спецификацию ECMA и прочитать ее относительно того что такое return Statement следом что такое try statement чтобы увидеть и понять поведение директивы (statement) return для этого случая. (Правильнее говорить не поведение дерективы, а поведение Jit или компилятора, потому что деректива управляет именно им)

А не вводить всех в заблуждение относительно того, что дескать у return ов идет война. Никакой войны нет. return это не оператор - это директива (statement), поведение которой зависит от обстоятельств в которых он находится.

Где в случае с try Statement - return в трех блоках ( catch, error, finaly) только устанавливают значение которое возвращается по завершению.

Пример с промисами

Если в первом случае еще можно было бы попытаться притянуть за уши попытку иронии на тему, не до конца интуитивно понятного синтаксиса в JS, то в этом случае откровенная безграмотность.

Правда, promise.finally() оказывает влияние на то, когда именно промис будет разрешён:

const wait = (ms) => new Promise((r) => setTimeout(() => r(), ms));  
const promise = Promise.resolve('one').finally(async () => {   await wait(2000);   return 'two'; });

В данном случае promise, всё так же, разрешается значением 'one', но на это у него теперь уходит две секунды.

Я сначала подумал что это некорректный перевод. Однако в оригинале тоже самое:

In this case promise still fulfils with 'one', but it takes two seconds to do so.

Что является совершеннейшей неправдой.

Даже не заглядывая в документацию относительно того, что возвращают те или иные методы Promise, проведя простой эксперимент увидеть:

const wait = (ms) => new Promise((r) => setTimeout(() => r(), ms));
const promise = Promise.resolve('one');

promise.finally(
  async () => {
    await wait(2000);
    console.log("Finaly")
    }
);

promise.then(
  (e) => console.log(`Fulfils: ${e}`)
)

то что наш промис разрешился значением one сразу же как к нему пришла в очередь в первом же блоке микротасков, а выполнение finaly произошло запланировано спустя не менее 2000мс, что никак не повлияло на то, когда разрешился промис не повляло.

Автор не в курсе, что async function возвращает сама обьект Promise, а не функцию, который попадает как значение, а не функция в метод finaly, что в таком случае заменяется на .finaly( () => Promise ); То есть значение оборачивается в функцию которая и становится cb для finaly которая возвращает промис.

Игого:

Как я говорил уже выше, Jake уже не первый раз садиться в лужу. И что хуже всего, он имеет достаточный авторитет для многих людей которые доверяют ему без вопросов, что очень зря даже в основах JS, что на примере выше наглядно видно.

Приёмы ускорения кода на JS и других языках: подборка от разработчика поиска Яндекса

Крайне противоречивое впечатление о материале. Создается впечатление, что это на скору руку собранный документ причем в разное время и разными людьми. Иногда описано то, что хочется перепроверить, а иногда откровенные фантазии человека который не дал себе труда докопаться до настоящих причин приводящих к тому или иному результату.

Судите сами:

Мутабельность

Первая проблема — плохая поддержка иммутабельности. Иммутабельность объектов означает генерацию новых объектов, иногда с довольно большой скоростью [...] убрать клонирование объектов и мутировать существующие объекты.

Давать рекомендации подобного характера в отрыве от платформы - это попросту сотрясать воздух. Потому делаем предположение что в данном случае речь идет о JS.

Первое чему учат людей, которые хотят писать высокопроизводительный код для JS это мономорфность функций и hidden class для обьектов. Благодаря которым V8 (и не только он) может применять эффективные методы оптимизации кода работы с обьектами. Как первое так и второе априори ставит под вопрос вменяемость совета о мутировании обьектов. Если Ваши обьекты мутируют, то вы не только проигрываете из-за того что не получаете эффективные оптимизации от v8, но и можете еще больше замедлить свой код в случаях, когда V8 примете решение о применении своих оптимизаций, а потом будет вынуждена проводить деоптимизации после ваших мутаций.

Zero memory allocation или GC-free

это безусловно очень правильное поведение при условии соблюдения того о чем говорится выше. То есть нужно не только использовать детерменированный пул обьектов, но пул обьектов с одинаковыми hidden классами. В противном случае Вы сократив издержки работы GC получите еще большие издержки в связи с тем, что к вашему коду откажутся применять хоть сколько нибудь эффективные оптимизации.

Чтобы подчеркнуть важность этого: разница в производительности при работе оптимизированного кода и кода который принято решение не оптимизировать, может составлять и 10 и 100 и более раз.

Потому по большому счету рекомендации которые даны в статье вредны, а что самое плохое делались человеком который не отдавал себе отчета в том, что рекомендовал.

map reduce filter etc...

Методы перечисленный выше не зря называют функциональными. Эти методы существую для реализации парадигмы функционального программирования, но не для бездумного применения map в качестве итератора по массиву. Ваша проблема, и проблема многих других, в том что вы и они понятия не имеют зачем map возвращает новый массив, для чего придуман reduce, и почему for никогда не будет быстрее forEach и что самое главное будет ему проигрывать в некоторых случаях в десятки раз.

Функциональное программирование, это парадигма со своими правилами, которые позволяют использовать математический аппарат позволяющий без анализа самого кода функции сделать вывод и ее идентичности другой функции, что в свою очередь позволяет JIT или компилятору применять к такому коду оптимизации вплоть до автоматического распаралеливания работы по разным потокам если они есть.

Всем кто хочет познакомиться с этой областью программирования рекомендую на youtube поискать лекции Виталия Брагилевского. Для того чтобы хотя бы получить представление о том, где когда и как нужно использовать функциональные методы.

Антипаттерн: накопление строк в массиве

Ещё один антипаттерн со времён шестого Internet Explorer — если нужно накопить длинную строку из кусочков, некоторые разработчики до сих пор сначала собирают эти строки в массив, чтобы потом вызвать join

это работало и работает по сей день и не только в IE. Большая проблема хипстеров пишущих микробенчмарки сравнивая тот или иной код в том, что они не понимают что сравнивают. Если я попрошу Вас сейчас набросать мне концепт такого теста, вы наверняка вляпаетесь в ровно теже проблемы что и все прочие, когда делали выводы либо о работе этого метода либо о противоположном результате. Я так категоричен потому, что ваша рекомендация о ConsString и рассказ легенды о IE прямо указывает на то, что Вы как им многие другие не понимали почему холивары на тему concat и + не утихали долгое время.

А проблема всегда была в том, что в большинстве случаев сравнивалось не время конкатенации, а время выделения ресурсов для обслуживания массива, и ресурсов для обслуживания строки состоящей из чанков. И как только тот же тест переписывается с исключением этой проблемы ( как самый простой способ - массив накапливающий строки должен иметь строго детерменированную длину равную количеству чанков) то результат внезапно становится совершенно другим. Когда вдруг array.concat оказывается быстрее ConsString

Вы безусловно правы в том, что в данном случае, это именно антипаттерн. Но обьяснение которое вы даете имеет мало общего с реальностью, и только лишний раз вводит людей в заблуждение относительно причин использования тех или иных методов и следствий такового использования.

Idle Until Urgent

Все верно с одним важны НО. Все таже мономорфность и все те же хидден классы. Если Ваш обьект используется раз за весь цикл работы кода, то можно делать и так как рекомендуют в статье. Но если Ваш обьект принимает активное участие в работе то есть обращение к нему происходит сотни раз, то реализация из статьи это похороны возможным оптимизациям со стороны V8. По причине того, что первое правило производительного кода JS это созданный обьект не должен изменять своей структуры.

Предсказание ветвлений (Branch prediction)

Совершенно верно то, что на уровне процессора существует масса оптимизаций кода в том числе и ветвлений. Только позвольте вам задать вопрос - вы вообще в курсе каким образом работает V8?

Вы отдаете себе отчет в том, что большая часть вашего кода никогда не будет собрана в машинный код, то есть будет исполняться на уровне байткода Ignition, на поведение которого и тем более оптимизации под архитектуру процессора Вы никак повлиять не сможете.

Вы отдаете себе отчет в том, что только в том случае если Ваш код попал в TurboFan вы можете предсказать его конкретную реализацию под конкретную архитектуру?

Даже я, человек который не вылазит из дизасембелра для двух архитектур далеко не всегда могу дать верный прогноз относительно того кода который выдаст turboFan.

И теперь для того чтобы ситуацию сделать еще более драматичной, для текущей x86 архитектуры, описание алгоритма оптимизации ветвлений на уровне процессора занимает почти 11 страниц 10 шрифтом. То есть, это оптимизации такого рода, которые ну совсем не для того кто пишет JS код. Но для того кто пишет оптимизирующие алгоритмы TurboFan.

Ровно по этим же причинам Ваши рекомендации относительно Доступ к памяти: направление итерации яйца выйденного не стоят. Даже если вынести за скобки все прохладные истории описанные выше, количество издержек накладываемых платформой которая выполняет ваш JS код в миллионы раз превысят потенциальные выгоды от учета архитектуры работы с памятью.

Единственная правильная рекомендация для таких случаев это - пишите код таким образом чтобы он был максимально предсказуем. То есть содержал минимум ветвлений и переходов. Это не только возможно но и правильно. Кому нужно сэкономить время прочитайте книжки классиков Кнут - искусство программирования, или Дэйкстру.

Даунгрейд кода: ES6 → ES5

Ноги таких рекомендация растут из ситуации которую создали программисты V8 в то время, когда реализация многих новых методов делалась как простой полифил написанный на JS. То есть это был ровно такой же JS код, как если бы он был написан самостоятельно, с той лишь разницей что он проходил все тесты. То есть полностью соответствовал спецификации с учетом всех пограничных случаев. Стоит ли говорить, что когда Вы написали свой код упрощая его до нельзя он работал быстрее?

В настоящий момент, насколько мне не изменяет память, в ES6 не осталось ни одной подобной функции.

И тут я должен высказать большое ФЭ в сторону процесса разработки V8. Ситуация подобная с деструктурирующим присваиванием, или теми же map reduce и прочими методами, сильно подорвали веру в то, что Вы как разработчики V8 всегда делаете все хотя бы на троечку. Отчего все ваши последющие увещевания, не использовать специфические оптимизации можно спустить куда подальше, именно потому, что не Вам решать как должен работать мой код, тем более в ситуациях когда вы скармливаете людям откровенную халтуру. Пусть и исправляемую в последствии. Потому как именно Вы являетесь причиной того, что даются советы о даунгреде es5 с целью увеличения производительности в 2021 году.

Игого

Из всей статьи, в некотором смысле можно оставить только часть касающуюся работы с алгоритмами. Все прочие рекомендации представляют из себя либо действительно работавшие на момент релиза хаки (как в случае с даунгрейдом) либо невесть откуда взявшиtся рекомендации напрямую противоречащие тому, как работает V8 даже 10 летней давности. (V8 взят за основу как подавляюще доминирующая платформа выполнения JS. Многие из вещей заявленных мной выше характерны и для CoreJs и для SpiderMonkey)

Рекомендации

Самой верной рекомендацией на текущий момент для людей которые не любят профилировать свой код, или не хотят разбираться в кишках V8 это писать код который был бы максимально простым и предсказуемым, следуя простым правилам: никогда не меняйте структуру обьектов. Пишите код так как будто он у вас типизирован. Иными словами создав ссылку на область данных (переменную) где лежит число, сделайте так чтобы там никогда ничего кроме таких же числе не появлялось.

Всегда помните, 90% всех оптимизаций на уровне V8 делаются для функций. Потому от того, насколько предсказуемы ваши функции напрямую зависит произвоидтельность вашего кода. Если у функции есть параметры, сделайте так, чтобы в эти параметры попадали всегда значения одного и того же типа.

Если есть что-то, что может сделать за вас платформа - пусть это делает она. Например не стоит городить циклы for там, где с этим прекрасно справиться forEach. Внимательно читайте документацию и пытайтесь представить что означает то или иное действие: применяя map к массиву вы создаете новый массив, что неизбежно ведет к издержкам на обслуживание этой структуры данных. То есть каждая операция чего то стоит, и нужно понимать чего.

И дайте себе труд посмотреть пару лекций на эту тему от людей которые понимают то о чем говорят. Например

Franziska Hinkelmann https://www.youtube.com/watch?v=p-iiEDtpy6I&list=WL&index=148

или Вячеслава Егорова https://www.youtube.com/watch?v=HPFARivHJRY

Стек вызовов JavaScript и ещё большая магия

Тем кто будет читать эти материалы и пытаться вынести для себя что-то из комментариев к байт коду.


Автор написал эти комментарии только для того чтобы попытаться показать логику происходящего на более интуитивно понятном языке. И все. Мне кажется что в таких случаях лучше рисовать блок схемы, чтобы случайно не вводить людей в заблуждение.


Иными словами — не в коем случае не стоит воспринимать реализацию логики из комментариев как ту, которая реализована внутри v8. Потому что последствия этого могут вам стоить многократного просева производительности.


Автору это условно простительно, так как материал совсем о другом. Но лично я бы все же настаивал на том, что если уж взялись разбирать байт код и не делаете ремарки отоносительно того, что разбор содержит грубые неточности в силу того что они не имеют отношения к теме, то комментировать нужно так как правильно.


Например код:
ThrowReferenceErrorIfHole [0]


Описан как:
if (a === undefined) throw("ReferenceError: %s is not defined", const[0])


Что совершенно неправильно.


ThrowReferenceErrorIfHole — это проверка ссылки на предмет того используется ли она в TDZ или нет. То есть это ситуация когда компилятор не может точно установить, сейчас эта ссылка используется уже после момента инициализации или до, то есть нет возможности точно предсказать находится ли сейчас этот кусок кода в TDZ или не находится.


И возвращение undefined является следствием этой проверки, а не тем что стало причиной.


То есть код вида


{
  const func = () => param1;
  let param1 = 1;
  func();
}

Совершенно валиден, не смотря на то что param1 инициализируется после объявления кложуры. Но, в этой ситуации компилятор на момент сборки кложуры func не может точно знать когда func будет вызываться, то есть нет строгой детерминированности относительно param1.


В силу чего компилятор вынужден ставить обязательную проверку ThrowReferenceErrorIfHole


LdaImmutableCurrentContextSlot [2]
ThrowReferenceErrorIfHole [0]
Return 

И такой код может выполняться в разы медленнее чем код вида


let a;
( a === undefined ) && ( a = 1 );

который будет преобразован в байткод:


LdaUndefined 
Star r1
TestUndefined 
JumpIfFalse Label1
LdaSmi [1]
Star r1
Label1:

Что радикально отличается от ThrowReferenceErrorIfHole и по обьему работы и по предсказательной силе для будущих оптимизаций.

CSS, JavaScript и блокировка парсинга веб-страниц

В силу того, что переводчик совершенно не ориентируется в теме материала, а оригинал написан безобразно получилась жуткая химера от которой вреда больше чем пользы.

Судите сами:

Если в теге <script> не используются атрибуты async или defer — процесс загрузки и обработки материалов страницы происходит так, как показано на следующей схеме. Загрузка JS-файлов и выполнение содержащегося в них кода блокирует парсинг HTML-кода.

Таким образом как показано на схеме, парсинг происходил 10 лет назад. С тех пор разработчики браузеров догадались, что ждать не обязательно и, как минимум, это время можно использовать для параллельной загрузки других внешних ресурсов, которые когда придет их время пройдут типичные для них шаги активации.

Правильно было бы писать, что показанное на схеме, это очень упрощенное отображение процесса, активации скрипта, которое в настоящее время хоть и имеет прямое отношение к реальности, но уже не оказывает драматического влияния на производительность (как это было раньше) в силу того, что все современные браузеры научились смотреть в будущее и готовить внешние ресурсы заранее.

Далее:

Когда браузер обрабатывает тег <script> с атрибутом async, загрузка JavaScript-кода осуществляется в асинхронном режиме. Код скрипта выполняется сразу после загрузки. При этом выполнение JS-кода блокирует парсинг HTML.

и

Если в теге <script> имеется атрибут defer — код скрипта загружается асинхронно. При этом код, после завершения его загрузки, выполняется только тогда, когда будет завершён парсинг HTML-кода.

Автор материала пытается пересказать спецификацию, но делает это способом который сбивает с толку переводчика, и получается неоднозначная формулировка когда можно подумать, что в случае async блокировка рендера происходит, а в случае defer нет. На самом деле это не так, на самом деле блокируют оба, только в силу особенностей поведения defer происходит это всегда в момент когда вероятность этого минимальна.

async и defer - как же все на самом деле

Радикальная разница async и defer заключается в том, что defer гарантирует активацию скриптов ровно в том порядке в котором они были обнаружены на странице, при этом момент активации в настоящий момент определен как точка ровно перед событием domcontentloaded. При этом async может выполниться в любой момент времени когда браузер решит что он готов это сделать, но при этом обязательно до события load.

Когда я говорю в настоящий момент, я хочу обратить внимание что все время спорадически возникают обсуждения новой спецификации, которая, предполагает активацию подобных скриптов без обязательной привязке к domcontentloaded, так как строго говоря, в современных реалиях такое поведение это почти тоже самое что лечить геморрой подорожником. Вроде как бы и лечит, только эффективность сомнительная.

Иными словами, тот факт что цепочка defer скриптов гарантированно выполняется перед domcontetnloaded дает гарантию только того, о чем говорит событие - html распасрили и dom готов, но не говорит о том, что если сейчас что то иницирует reflow он не будет заблокирован работающим defer скриптом. Он будет заблокирован ровно так же как и async и любым другим скриптом, за исключением workero ов. В результате мы вроде бы как поток основного построение DOM и не блокировали и должны радоваться, только все мы знаем что современный проект почти всегда это не просто DOM но и JS логика. Как итог, вспоминаем про подорожник.

Именно по этой причине, при построении приложений где производительность играет ключевое значение, никто не использует ни async ни defer в силу их текущей практической бесполезности (за исключением одного особого случая, о котором я напишу ниже) и именно поэтому возникают идеи изменить спецификацию и дать возможность выполнения скприта без привязки к событиям domcontentloaded и load

Если не async и defer то что и как?

Организация современного приложения в условиях строго детерминированного бюджета выделяемых ресурсов на его работу, должна выстраиваться на основе Service Worker ов с cache API и строгим контролем fetch запросов с учетом текущего IDLE браузера. Что реализовать 10 лет было невозможно, а сейчас стало не просто реальностью - но стандартом дефакто

Что за особый случай для async и defer о котором говорилось выше

Не смотря на почти полную бесполезность этих атрибутов в реалиях современной разработки, разработчики V8 (насчет других неуверен, кажется в Spider Monkey так же) все таки нашли еще одну возможность реанимировать эти два зомби. Сейчас указав скрипту этот атрибут Вы не просто измените поведение его загрузки и точку его активации, но дадите возможность браузеру провести парсинг и компиляцию части скрипта за пределами основного треда, в отличии от классической схемы, где парсинг с компиляцией пройдет в основном треде со всеми вытекающими.

В результате этой микро фичи, некоторые проекты, в основе которых не закладывались какие либо претензии к производительности могут получить существенное ощутимое изменение в фазе холодного старта. Касается это тех приложений которые до сих пор весь свой код собирают в единый большой жирный красивый толстый бандл, вешая поверх него рюкзак с полифилами и давая в руки плакат - я сделяль. То есть в ситуации когда компиляция занимает ощутимое время указанием defer или async мы помогаем браузеру разрешая ему собрать это безобразие в отдельном потоке.

Отдельного внимания заслуживает процесс кеширования байткода да и сам процесс компиляции. с 2015 года браузеры использующие v8 получили возможность кешировать не просто файл скрипта, но и байткод получаемый при его выполнения. Google Chrome например с 2015 года это делает. При этом, логика работы этого хозяйства, то есть по какой причине были выбраны именно такие алгоритмы, а не другие, для меня, человека знающего до последней ассемблерной команды эту часть работы, до сих пор не понята.

Итого

Построение отзывчивого интерфейса в условиях больших обьемов JS логики, давно ушло за рамки борьбы с блокированием построения DOM дерева и началом его рендера. И требует сейчас достаточно неплохого знания современных технологий, от Wotker ов, WorkLet ов, до принципов компиляции современными платформами JS кода.

Google не так давно стал заявлять, что в 2022 году начнет активно внедрять метрики, которые будут опираться уже не просто на скорость рендера, но и на обьемы потребляемой памяти и обьемы затрачиваемого процессорного времени.

Паттерны отложенной инициализации свойств объектов в JavaScript

Этот материал — прекрасный примера случая, что происходит когда кто-то начинает заниматься производительностью не производя хотя бы самых элементарных замеров.


Динамическое изменение колличества и характера свойств обьекта в JS — автоматически влечет за собой целый ряд последствий все из которых связаны с деоптимизациями кода работающего с этим обьектом, или изменения внутреннего представления этого обьетка из формы обеспечивающей максимальную производительность для доступа к его данным к форме драматические влияющей на работу с ним.


Одно из первых правил работы, которая предполагает максимальную эффективность кода, это неизменность объекта с момента его объявления. Имеется ввиду его структура, а не данные. То есть такие действия как удаление свойства, добавления свойства, изменения его характера строго противопоказаны.


Подробнее об этом можно увидеть на любой презентации от Google относительно производительности кода для V8 выпускаемых с 2016 года. Уровень сложности таких видео от 10+ а польза значительная.


Рекомендую например
Franziska Hinkelmann: JavaScript engines — how do they even? | JSConf EU
и полезно, и девушка рассказывает что особенно полезно для начинающих бородатых джаваскриптеров.

Доступность — это просто, Или 5 смертных грехов доступности

Просьба
Я Вас очень попрошу попробовать на меня не обижаться за все то, что я напишу ниже.


Я не нисколько не хочу Вас обидеть или поставить под сомнение Вашу квалификацию.
Мой агрессивный, предельно возмущенный тон, продиктован ровно теми же причинами, которые Вас заставили попытаться разобраться в этой теме. И к сожалению, Вы стали жертвой сложившейся ситуации.


Сами скринридеры, разумеется, не видят страницу и не понимают, что перед ними находится. Поэтому наша задача, как разработчиков, с одной стороны, предоставить скринридеру как можно больше данных, а с другой стороны, не мешать ему работать.

Совершенно справедливо. И для этого существует стандарт семантической верстки HTML5 которую большая чатсь скринридеров либо игнорирует, либо интерпретирует неправильно. И их нельзя за это судить, конечно, в силу истории становления стандарта.


Грех 1. Бардак в заголовках


В HTML существует шесть уровней заголовков, которые обозначаются тегами от H1 до H6 и используются именно в этом порядке, создавая иерархическую структуру.

То о чем Вы пишите в этом разделе, касается исключительно норм стандарта HTML4, потерявшим свою актульность в 2009 году и не имеет ничего общего со стандартом HTML5.
Иерархия заголовков h1-h6 это спецификация структурирования документа из стандарта HTML4, которую для обратной совместимости сохранили в HTML5 придумав для этого сложнейший алгоритм формирования неявных секций.
Чем допустил громадную ошибку, о которой им тогда говорили в том числе и я в составе других орущих заинтерисованных.


Первые версии черновика HTML5 вообще исключали теги h1-h6 из допустимых тегов.
Должен был быть только тег h. К сожалению продавленное решение обратной совместимости, привело к сохранению h1-h6 и созданию алгоритма формирования неявных секций, который по своей сложности превышает весь html5 стандарт вместе взятый.


Но самое главное не это, а то что в 2021 году, люди вроде Вас до сих пор думают, что структура документа формируется именно этим образом. А между тем, правила формирования документа были кардинально изменены в 2009 году, когда черновик стандарта html5 быть признан готовым к началу процедуры стандартизации.


Формирование аутлайна согласно html5 спецификации семантической верстки, происходит за счет уровня вложенных секций, у которых может быть заголовок с любой цифрой.


Иными словами, в отличии от html4 где была совершена неудачная попытка построения структуры документа заголовками, был реализован почти универсальный алгоритм формирования структуры любой сложности, где степень специфичности контента, определялось его уровнем вложенности, а не номером заголовка у тега h.


В спецификации html5 номер заголовка не имеет НИКАКОГО ЗНАЧЕНИЯ. за исключением особого случая, когда верстальщик в нарушение спецификации, в одну секцию добавляет больше одного заголовка. В этом случае запускается алгоритм формирования неявных секций, для разрешения конфликтной ситуации.


Люди из добрых побуждений, не хотели принимать мысль о том, что не внеся радикальное правило, о не валидности такой верстки, своими действиями приведут все к коллапсу. Что и случилось.


Сейчас в 2021 году, единицы знают как правильно формировать аутлайн в html5 стандарте. И десятки тысяч думают, что иерархия заголовков h1-h6 это именно то, что согласно стандарту должно выполнять эти функции.Что естественно не так.


Грех 3. Невидимые картинки
Согласно стандарта html5 трактования тега img зависит от трех его состояний:
главное — наличие атрибута src с корректным значением, в противном случае этот элемент ничего не представляет.


После чего оценивается три состояния атрибута alt. А именно:
1) alt атрибут отсутствует вообще — должно интерпретироваться как изображение которое представляет основной контент, при этом на момент его публикации определить альт атрибут не было никакой возможности.
2) alt атрибут задан пустым значением — должно интерпретироваться как изображение сервисного характера. ДЕкоративное изображение. То есть изображение которое не имеет никакого отношения к контенту вообще.
3) И, конечно, alt атрибут задан.


В силу сложившихся обстоятельств, громадное количество людей, в том числе авторов ПО читалок, стали заблуждаться ровно так же как и Вы. И относительно заголовков и изображений и много чего другого в стандарте HTML5. А виной тому стала одна корпорация, которая вложила в стандарт больше всех сил, а именно Google.


До 2018 года, не существовало ни одного стороннего инструмента, который бы мог подтвердить или опровергнуть правильность интерпретации той или иной семантической структуры. Фактически с 2009 года по 2018 год, всем html5 стандартом можно было только клопов давить.
Что все и делали, потому что ни теги, ни вся его семантика НИ НА ЧТО не влияла.


Авторы Читалок, рынок которых формируется совершенно особым образом, вынуждены решать две задачи, с одной стороны читать тот бардак который верстают люди, с другой стороны попытаться понять как работать со стандартом, у которого ничего кроме бумажной спецификации, написанное инопланетянами для инопланетян — нет.


Все текущие рекомендация W3C на которые вы ссылаетесь, написаны людьми не имеющими и малейшего отношения к формированию стандарта. Как и сама w3c.


На сегодняшний момент де факто, мы имеем ситуацию, когда большинство участников рынка читалок, имеет ПО которое чуть более чем полностью НЕ соответствует стандарту. И фиг бы с ним если бы не 2018 год.


Хаос начался в 2018 году, когда вдруг гугл в своем алгоритме ранжирования контента начинает учитывать семантику HTML5 именно так как она выписан в стандарте.
Которому как я написал выше протоиворечит работа читалок.
Традиция работы которых формировалось в диком мире и никем не регулировалась почти 9 лет.


И черт бы со всем этим было бы во второй раз. В конце концов, HTML5 аутлайн настолько гибок, что можно и соблюсти правила заголовков h1-h6 и нормы HTML5, только вот беда,


Вы и многие подобные Вам, распространяют чепуху относительно того КАК нужно верстать правильно. Настаивая на, не выдерживающей никакой критики, форме H1-H6 заголовков, не позволяющим решать насущные задачи даже в далеком 2003 году. Когда стали думать о html5.


В чем конечно Вы не виноваты. Ну разве что совсем немного в том, что прежде чем писать такой материал, не дали себе труда прочитать стандарт HTML5 в его оригинале от группы WHATWG, которая занималась им с 2004 года, и который поддреживается ВСЕМИ браузерами. А не то недоразумение которое w3c выкладывало якобы как официальный стандарт.

Редактор кода Visual Studio Code. Самый подробный гайд по настройке и установке плагинов для начинающих

Запуск на слабой машине

Когда программа установлена, можем ее запустить. Но запустится она не на каждом компьютере. Дело в том, что программа достаточно ресурсоемкая. Поэтому на слабой машине можно получить такой результат: вместо интерфейса программы черный экран, а процессор потеет на все 100%. Но выход есть — необходимо открыть контекстное меню ярлыка программы и дописать в пути к файлу вот такой флаг: --disable-gpu

Это наверное такой анекдот да?


Закатить раскатить

Как причина проблемы так и способ ее решения никакого отношения к слабым машинам не имеет.
Тем более не вполне понятно как автор, путем отрезания от слабой машины заметной части ее мощностей, вдруг решает проблему.


Если Ваша проблема решается при помощи disable-gpu то это говорит только о том, что по каким то причинам, webkit не может корректно взаимодействовать с вашей видео картой. Что может случаться совершенно на любой машине.


Соответственно, первое из решений, это не отключение функционала, опирающегося на плотную эксплуатацию вашей видео карты, а поиск причин почему это не происходит корректно. Иными словами, прежде чем переходить к действиям описанным ниже, следует убедиться что драйвера видеокарты работают корректно. Нередко простое обновление драйверов решает все проблемы.


Убедились что проблем с драйверами нет
Итого перед нами vscode который по каким то причинам не может запуститься с использованием аппаратного ускорения графики. При этом disable-gpu проблему решает и приложение запускается.


Закатить раскатить

В этом случае вам следует обратиться к целому зоопарку опций запуска вебкит бейсид приложений, которые позволяют менять почти все, кроме разве что ошибок в днк.


Перебираем опции командной строки
Вот тут https://peter.sh/experiments/chromium-command-line-switches/ вы найдете актуальный список ключей командной строки. Вас в первую очередь интерисуюет все что связано со словами, gpu compositing, threading, accelerated


Попробуйте начать со следующих опций, при этом пробовать варианты их как со словом disabled так и со словом enabled:


  • --ignore-gpu-blocklist
  • --enable-zero-copy
  • --disable-gpu-vsync
  • --disable-gpu-driver-bug-workarounds
  • --disable-gpu-driver-workarounds
  • --ui-enable-zero-copy
  • --enable-gpu-rasterization
  • --enable-dom-distiller
  • --enable-hardware-overlays
  • --enable-gpu-memory-buffer-compositor-resource
  • --use-gl=
  • --force-system-compositor-mode
  • --disable-low-res-tiling
  • --enable-native-gpu-memory-buffers
  • --enable-threaded-compositing
  • --use-angle=gl

Владельцам гибридной видео графики


Закатить раскатить

Если ваша машина использует гибридную графику, что то вроде оптимуса, или других забавных проявлений инженерного гения от нвидиа, попробуйте опиции с переключением на конкретный GPU. Однажды был случай, когда интегрированная Intel с 64г на борту оказалась на порядок быстрее дискретной нвидиа.


Практически всегда можно найти тот набор магических комбинаций, который не только решат проблему, но и в случае если ее не было, могу сильно повлиять как на производительность так и на потребление памяти в купе с шумящими кулерами.


Несколько решений из собственного опыта


Закатить раскатить

Например неожиданно подлагивающий на пол секунды интерфейс решался при помощи
--disable-gpu-vsync


опции --disable-gpu-driver-workarounds и --disable-gpu-driver-bug-workarounds, которые казалось бы должны помогать на самом деле приводили к проседанию производительности


а шаманство со значениями параметров --use-angle= и --use-gl= приводило к кардинальному изменения отзывчивости.


Кроме этого, можно сэкономить небольшое количество ресурсов отключая ненужные Вам апи, или функционал чем то вроде:
--disable-login-animations --no-default-browser-check --no-pings --disable-speech-api


Все вышеописанные шаманские рекомендации справедливы для любой ситуации связанной с вебкит бейсид приложениями. То есть и типичный гугло хром подобными кастрациями можно заставить шевелиться побойчее.

До свидания, Google Fonts. Последний аргумент

О шрифтах и кешировании


Теперь шрифты Google Fonts больше не кэшируются!

Шрифты как кешировались так и кешируются. Вероятно Вы хотели сказать сказать, что
Изменилась механика идентификация любого ресурса в кеше, а не только шрифтов.
Сильно упрощая — теперь кеш проекта A это только кеш проекта A, вне зависимости от того что в нем лежит. И ни один другой проект не может ничего получить из этого кеша. Раньше кеш был общим для всех.


Возможность эта была чрезвычайно полезной в то время, когда люди получали доступ к сети благодаря модемам 14400, то есть каждый лишний килобайт был причиной продолжительного ожидания.


С тех пор, как ситуация с доступом изменилась, издержки на соединение с хостом стали намного значимей, чем лишние загруженные килобайты. Именно потому, как Вы верно заметили, уже очень давно, в среде оптимизаторов, существует базовая рекомендация:
все ресурсы которые нужны вашему проекту должны загружаться от туда, куда пришел запрос


Разбор прочих несуразностей материала


Раскатить-закатить

О local


Но в последнее время Google удалила фунцию local() из @font-face в Google Fonts! То есть шрифты Google Fonts теперь не могут считываться локально, если использовать API.

Убран он был абсолютно правильно и убран был по простой причине — шрифт загружаемый извне, далеко не всегда бывает ровно тем, что лежит у пользователя локально.
Сейчас стало далеко не редкостью ситуация, когда локально можно обнаружить и Material Icons в трех версиях и Roboto и Noto, версии которых безнадежно устарели, но браузер то этого не знает. Он послушно берет локальную копию и отображает кашу на экране, которую, в рамках Google Fonts никак нельзя проконтролировать.


О справочнике Марио Ранфтль


Марио Ранфтль создал очень полезный справочник google-webfonts-helper.

Этот справочник не делает НИЧЕГО кроме того, что уже делает тот же Google Fonts. И по возможностям отличается разве что интерфейсом. При этом обладая ровно теми же проблемами что и оригинал. Первая из которых — список предлагаемого не отвечает действительности и просто является точной копией того что показывает сам Google Fonts.


Между тем Google Fonts это намного больше чем то что там отображено. Например вы до сих пор не найдете там Material Icons который там есть в 5 вариантах. И так далее и тому подобное.


О оптимизации


Это делается через подсказку preload.

Я немножко вас старше, а потому имею маломальские основания вам советовать. Никогда не подписывайтесь под документом смысла которого вы не понимаете.
Худшее что сейчас можно сделать при оптимизации проекта, это влепить неконтролируемый preload шрифтов на стадии загрузки проекта. Как впрочем и любого другого ресурса.
Вообще забудьте навсегда о существовании таких вещей как async defer pereload preconect
Если они Вам помогают, значит у проекта серьезные архитектурные проблемы. И решать их при помощи этих волшебных механизмов это тоже самое что использование подорожника для лечение гемороя.


О причинах изменения спецификации


Однако в последнее время появились идеи, как его эксплуатировать во вред людям.

Эти идеи появились и использовались ровно с того момента, как появилась спецификация на кеш. Люди работавшие над спецификацией, не были патологическими идиотами. И суть самой идеи, как раз и лежит в общем кеше. Google оттягивал свой конец так долго как мог.


Основная проблема подобных решений заключается в том, что сейчас существуют десятки других возможностей проделать тоже самое. И убивать ради закрытия одной из них, механизм, который обладал крайне полезными качествами в областях далеко за рамками загрузки шрифтов, это предел непродуманности.


Оказалось, что по отклику браузера можно определить

Никого в рамках этой задачи не волнует отклик браузера. Какое то чудо в перьях не подумав ляпнуло, все стали тиражировать.
А волнует тут прежде всего возможность благодаря отсутствию запроса вообще однозначным 100% образом идентифицировать поведение пользователя в рамках подконтрольных злоумышленнику ресурсов.


Например: я Цукер Маркенберг. И у меня есть ну очень популярный сайт МордоКнига. Поскольку я не просто Цукер, но еще и денег хочу, я начинаю монетизировать трафик подсовывая людям рекламу. В том числе и перед выборами. Эффективность моей работы напрямую зависит от того, что я знаю о поведении посетителя. Но вот незадача, отовсюду полезли разного рода припоны подобной идентификации. Как мне быть? Ведь это же несправедливо, когда я в рамках своей мордокниги не могу просто так выяснить такие мелочи. В результате мне приходит в голову решение, когда я каждому посетителю на его мордокнигу, кладу картинку 0x0 пикселей. Только название картинки является хешем, с закодированной информацией. Дальше, уже дело техники сверить при посещении чувствительного к статистике ресурса, логи запросов таких изображений, с логами посетителей. И однозначным образом идентифицировать каждого из них.


В сильно упрощенной схеме это работает именно так. А не мифические замеры скорсоти ответа. Тем более что латенси может возникать по десятками причин, совсем не связанным с кешем.


Что делать


Печально, что из-за приватности приходится жертвовать производительностью и делать лишние сетевые запросы.

Не писать чепухи, а подтянуть свой уровень в этой области. Уже давно проблемы производительности в том числе с загрузкой шрифтов, решаются иными способами. Слава богу браузеры давно дали нам в распоряжение массу механизмов, о которых ранее мы могли только мечтать. Из которых возможность контролирования любого сетевого запроса на уровне woirkera первейший механизм с которым я рекомендую ознакомиться.

Простой веб сервер для SPA/PWA за «5 минут»

Это прекрасно. Чрезвычайно талантливо, это ж нужно было умудриться, client side rendering обозвать spa и pwa. И если первое хоть какое то отношение имеет к заявленной теме, то pwa которое является распиаренным гуглом термин, обозначающий привязку файла манифеста к любой html страничке отображающей hello world, требовало наверняка очень развитой фантазии.

20 SEO-мифов, которые должны умереть в 2020

крайне приятно, когда среди представителей сео сообщества появляются люди, пытающиеся прыгнуть выше головы. Это достойно всяческого уважения. Кроме, разве что, нескольих типичных для сео спецалистов проблем, а именно повальная техническая безграмотность, и общее стремление заменить одну сказку другой.


Ну вот например пункт 6 о дескрипшине. Я уже предвкушаю как вытянется ваше лицо, когда вы откроете для себя кореляцию текста дескрипшина тайтла и заголовочного контена на странице, как задергается бровь когда откроете для себя возможность такими кореляциями получать максимальные сниппеты в гугле. А уж про магазины с даже боюсь и говорить, пусть сюпризом будет.


Или вот 9 пункт. Ну что же вы не вникли в тему-то? Вам бы уж точно следовало бы знать, что с 2015 года, то есть момента стандартизации семантики в штмль5, размечая страницу как доктайп штмль, заголвки не имеют того влияния как это было в славрое время htm4, но имеет влияние связанность секций и их вложенность друг в друга.
Именно по этой причине совершенно неважно сколько у вас заголовков, и какой у них немер, потому как всю работу теперь делают секции.
Конечно вы сейчас скажете — мол "но я же вот же заголовок вот же и оно же" чем опять заставите думать о Вас как о типичном сеошнике в силу простой причины — страница ваша, которая наверняка с тем самым доктайпом, размечена неправильно, и вы все время оказываетесь в ситуации, когда каждый новый заголовок должен создавать неявные смысловые секции. Тот самый случай, когда совокупность неверных шагов может дать результат.


Переступите через себя, почитайте про семантическую верстку, войдите в курс современных веб технологй.
Чтобы не писать нелепости про изображения. Наконец разобраться для чего и как пишеться альт атрибут, ну и разобраться в том, что такое отзывчивость. А то странновато в 2019 году рассказывая про оптимизацию размера картинки в срц теге, когда изображение давно уже не представляют одним файлом, а массивами изображений в одном теге.


Чтобы вам стало интереснее — современное сео, при оптимазации одного изображения оперирует цифрами от 12 файлов на одну картинку.


Всяческих вам благ и технического роста.

Новые типы микроразметки для расширенных интерактивных сниппетов

Очередной пример мифотворчества от SEO господ, которым нужно подтянуть свою техническую грамотность.
Рекомендация: когда появляется новый тип микроразметки, используйте инструмент Rich Results Testing Tool

Который появился только год как, до сих пор не вышел из состояния пре-беты, и не умеет показывать и половины сниппетов. А те которые умеет, часто, показывает неправильно.

Ещё одно крайне полезное нововведение, связанное с новыми типами микроразметки, — возможность использовать несколько типов разметки на одной странице.

Так было ВСЕГДА. Это суть микроразметки — разметить весь контент на странице.

Product HowTo FAQ Orgainzation это не что-то, что определяет суть страницы, а то, что определяет то, что конкретно показано в конкретном блоке. Иными словами, любая страница может содержать и должна содержать десяток типов разметки, описывающих весь контент на странице.

Как работают поисковые системы

Т.е. вы тоже считаете, что нужно в коде текст двигать прямо под открывающий body? Ну ок.

я не считаю. я знаю, что физическое положение контента в первой области видимости имеет прямое влияние на ранжирование. Повторяю для не внимательных — это объективная реальность которая легко проверяется простым тестом: купите два домена. На каждом генерируйте синтетический контент с одним термином, только на одном ключевой термин расположите в первой области видимости. На втором расположите на удалении.
Запустите два домена в индекс.

Для полноты эксперимента, купите третий домен, на нем точно так же разместите контент с тем же термином, но в верстке используйте css variables или grid, таким образом, что order или положение контента будет напрямую зависеть от технологии, и находиться глубоко ниже первой области отображения.

Дальше объяснять?

Как работают поисковые системы

я это уже лет 10 слышу.Ищет все хуже и хуже, а популярность все та же и та же)

Яндекс уже даже в РФ вылетел за пределы 50% рынка поиска. Про рынки других стран и говорить нечего.

Да, рендерят. Гугл точно, но и Яндекс вроде в рамках возможностей. Один из древних мифов seo — запихнуть текст так, чтобы он был как можно выше в исходном коде и пофиг где на странице.

Это не миф. По крайней мере в плоскости гугла и определения его(контента) физического положения в области отображения, а не в коде. Что подтверждается как рекомендациями самого гугла, так и очень простым экспериментом.
Ассессоры. Толока.

В статье как раз очень хорошо показывается проблема Ассесоров. Которая делает их полностью бесполезными как раз в узких нишах:

мнения двух «асессоров» (специалистов, выносящих вердикт о релевантности) в среднем не совпадают друг с другом в очень большой степени! Отсюда вытекает и естественная верхняя граница качества поиска, ведь качество измеряется по итогам сопоставления с мнением асессора.

Браузерная ленивая загрузка изображений (атрибут loading)

Появление этого атрибута прекрасная иллюстрация к поговорке — хотели как лучше, а получилось как всегда.

В текущей его реализации, это абсолютно бесполезная технология и вот почему:
  1. Атрибут не работает с любым изображением содержащим srcset и sizes — а это сейчас стандарт по умолчанию.
  2. Атрибут не дает возможности контролировать свою работу. СОВСЕМ. Он вещь в себе, которая делает то, что ему хочется. Параметры активации прибиты гвоздями в коде браузера
  3. В текущей реализации, вне зависимости от того где изображение, браузер все равно создаст запрос к серверу и скачает около 2 килобайт, для того чтобы определить его размеры. И повлиять на это нельзя


Как итог, выпускается обрубок, который не работает даже со всеми валидными вариантами верстки того же IMG, не говоря уже о том, чтобы послушать людей которые работают с подобной технологией по 15 лет, для которых она как бы и должна была быть создана.

Обрубок, который кардинально НИКАК не повлияет на производительности страницы, потому что в любом случае создает соединение на каждое изображение и нагружает канал.

Полезен будет только той категории людей, которые до сих пор изображения верстают как
<IMG src=  >

и по каким то своим причинами использовать чужой код не хотят, а свой написать не могут, но при этом доросли до того, чтобы перевестать до
<IMG src=  loading="lazy">


Все же, кто использовал Lazyload не как игрушку, как использовали свой код, так и будут продолжать использовать.

В гостях у Владимира Лихачева, отца Николая Лихачева, более известного как Крис Касперски

Я все тогда не мог понять, каким образом он находил время отвечать всем. Даже на самый пустяковый и бессмысленный вопрос. Даже на почту, в которой ничего кроме «Привет как дела» — не было. А главное зачем ему это было нужно.

Сейчас, вспоминая все переписки с ним, кажется, что это была попытка избежать одиночества. Общением с тысячами знакомых и не знакомых ему людей он заполнял какую то дыру внутри себя. Обсасывая каждый байт в коде, он как будто бы хотел, чтобы диалог продолжался, как минимум, бесконечно.

Информация

В рейтинге
5,516-й
Откуда
Харьков, Харьковская обл., Украина
Дата рождения
Зарегистрирован
Активность