Size: a a a

Иван Акулов про разработку

2020 December 17
Иван Акулов про разработку
В чем же тогда профит? Профит в том, что с помощью этого можно уменьшить Total Blocking Time.

Проблема
Представьте, что вы используете в приложении модуль vimeo-player, и этот модуль при импорте выполняет какой-то дорогой код:

// vimeo-player/index.js
...
const { deviceKind } = parseUserAgent() // занимает 100 мс


Если вы проимпортируете этот модуль стандартным импортом:

import vimeo from 'vimeo-player'

— эти 100 мс добавятся к времени инициализации бандла и увеличат Total Blocking Time.

import()
Функция import(/* webpackMode: 'eager' */) позволяет отложить модуль до момента, когда он становится нужен. Если вы замените

import vimeo from 'vimeo-player'

на

import(/* webpackMode: 'eager' */ 'vimeo-player')
 .then(vimeo => ...)


то эти 100 мс не будут потрачены, пока вы не вызовите import().

Если vimeo-player нужен редко, то это здорово уменьшит общий Total Blocking Time. А благодаря /* webpackMode: 'eager' */ модуль останется в том же бандле — и будет доступен сразу же, без траты ещё 200 мс на загрузку.
источник
Иван Акулов про разработку
​​require()
Ещё один способ соптимизировать TBT таким образом — это использовать require():

const vimeo = require('vimeo-player')

Как и import(/* webpackMode: 'eager' */), это:
— оставит модуль в текущем бандле
— и не выполнит его, пока вы не вызовите require()

Плюс такого подхода — require() сразу же вернёт модуль, а не промис на модуль. Благодаря этому рефакторить существующий код чуть проще.

Минус — он плохо поддерживается. Смешивать import-ы с require нельзя в Rollup, в mjs-модулях в webpack-е и мб где-то ещё:
источник
2020 December 23
Иван Акулов про разработку
​​— Вижу в бандле пакет, но не понимаю, как он туда попал. Как разобраться?

Тут есть два способа: простой и надежный.

1) Простой: если у вас Yarn, вызвать yarn why название-пакета. yarn why покажет, почему этот пакет установлен.

Например, здесь видно, что @emotion/stylis попал в бандл потому, что от него зависит styled-components:
источник
Иван Акулов про разработку
​​(В npm аналогично работает npm ls название-пакета)
источник
Иван Акулов про разработку
​​2) Надёжный:

Способ с yarn why (или npm ls) — простой, но не всегда корректный. Например, yarn why может напечатать несколько пакетов, а не один. Или библиотека может быть установлена одним пакетом, а импортирована другим.

Когда есть сомнения, я люблю проверять их через webpack.github.io/analyse. Вот как это работает:

— Билдите бандл с плагином webpack-stats-plugin
— Получившийся JSON-файл загружаете в webpack.github.io/analyse
— В Modules находите нужный вам модуль
— Кликаете на него и смотрите, что указано в Reasons

Вот как выглядит отчёт для пакета @emotion/stylis (точнее, его главного файла dist/stylis.browser.esm.js). Здесь видно, что файл попал в бандл, потому что его импортирует styled-components:
источник
Иван Акулов про разработку
А также: вопросы, вопросики, вопросища, ¿⸮⁇;

Я напоминаю, что мне можно задавать любые вопросы по перформансу. Вопрос выше, например, задал Никита Кирсанов в твитере.

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

Пишите прям тут в комментариях. На какие-то вопросы я, возможно, отвечу прямо в канале 🙂
источник
2021 January 24
Иван Акулов про разработку
​​Pure-комментарий

Если вы однажды заглянете в неминифицированный бандл, то в куче мест¹ вы увидите вот такой автоматический комментарий:

/*#​__PURE__*/

Что это за комментарий?

(¹ — точно увидите в Реакт-приложениях, с другими фреймворками не проверял)
источник
Иван Акулов про разработку
​​1) В 2016 кто-то заметил, что, если пропустить JS-класс через Babel, этот класс перестанет три-шейкаться. То есть webpack не сможет удалить этот класс из бандла — даже если он нигде не используется.

React-компоненты тогда активно использовали классы, поэтому для React-приложений это был kind of a big deal.
источник
Иван Акулов про разработку
​​2) Почему это происходило?

В 2016 классы были просто синтаксическим сахаром вокруг функций. Поэтому Babel конвертировал классы в функции — и оборачивал эти функции в IIFE («immediately invoked function expression» — «функция, которая сразу же вызывается»).

Выглядело это примерно вот так:
источник
Иван Акулов про разработку
​​3) Проблема с IIFE в том, что UglifyJS (который тогда отвечал за три-шейкинг в webpack-е) не знал, когда этот IIFE безопасно удалить.

IIFE может просто создать и вернуть класс — и больше ничего не делать. А может попутно отправить запрос на сервер. UglifyJS не знает, что именно происходит внутри IIFE — поэтому не может его убрать.
источник
Иван Акулов про разработку
​​4) Чтобы решить это, придумали комментарий /*#__PURE__*/.

/*#__PURE__*/ обозначает, что вызов функции, который идёт сразу за ним, не имеет никаких сайд-эффектов. То есть этот вызов не изменит ничего в приложении — и от его удаления ничего не поменяется.

И в 2017-м Babel начал добавлять /*#__PURE__*/-комментарий перед IIFE, которые он генерирует. А UglifyJS начал распознавать этот комментарий — и удалять pure-функции, если результат их вызова не используется:
источник
Иван Акулов про разработку
5) А дальше произошло вот что:

— Куча других инструментов тоже начала использовать комментарии /*#__PURE__*/. Например, babel-preset-react добавляет их перед React.createElement, а babel-plugin-styled-component — перед styled.button, styled.div и т.д.

— Появился Terser — форк UglifyJS. Terser стал минификатором по умолчанию в webpack и по-прежнему отвечает за бо́льшую часть три-шейкинга

/*#__PURE__*/-комментарий появился в документации Terser (вкупе с парой других специальных комментариев): https://terser.org/docs/api-reference.html#annotations

— А эта история стала моим любимым рассказом на конференциях (потому что /*#__PURE__*/ играет огромную роль в уменьшении размера бандла — и никто про него не знает!)
источник
2021 January 28
Иван Акулов про разработку
Кстати, классный Валя Семирульник завёл классный канал @valya_reads_issue и пишет там про про ускорение билдов и фронтопс. Вот про TypeScript:

#добраярекомендация
источник
Иван Акулов про разработку
Инкрементальная компиляция в TypeScript

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

У тайпскрипта есть опция incremental. При её включении TS складывает информацию о проекте в .tsbuildinfo файлики, а при последующих запусках использут их для ускорения проверки типов и эмита файлов.

В Альфа-Банке мы смогли ускорить компиляцию в 7 раз, с 2 минут до 17 секунд.

Кстати, у тайпскрипта в wiki на гитхабе есть страничка с названием Perfomance. Там вы можете найти как опции для ускорения компиляции, так и способы написания кода, которые тайпскрипт сможет переварить быстрее.
источник
2021 March 02
Иван Акулов про разработку
Long time no hear! Сегодня поговорим в Клабхаузе с Ромой Лютиковым (перф-инженером в Pitch) про то, как готовить перформанс в Реакт-приложениях. Ну и послушаем ваш опыт, конечно.

Сегодня, 17:00 по Киеву · 18:00 по Москве

Приходите (особенно если у вас большое Реакт-приложение, и вы там чё-то оптимизировали — ужасно интересно послушать): https://www.joinclubhouse.com/event/xeg9GqNG
источник
2021 March 19
Иван Акулов про разработку
Любимые перф-инструменты

Собрал список любимых перф-инструментов, про которые мало кто знает. Ловите:
источник
Иван Акулов про разработку
1️⃣ Slowfil.esSlowfil.es

slowfil.es даёт ссылку с огромным (и настраиваемым) временем ответа сервера.

Супер-удобно, чтобы посмотреть, как сайт поведёт себя, если какой-то CSS или JS-файл начнёт грузится вечно
источник
Иван Акулов про разработку
2️⃣ Input Delay

input-delay.glitch.me даёт повводить текст в поле ввода, которое лагает на 50-150 мс. (Ужасно бесит.)

bl.ocks.org/esjewett/2b188f00eef012507ae3 делает то же самое, но с курсором мыши.

Оба тула идеальны для демок
источник
Иван Акулов про разработку
(Также в тему: трёхминутное видео Майкрософта, которое показывает, насколько сильно ощущается разница между лагом в 100 мс и в 5 мс: https://www.youtube.com/watch?v=vOvQCPLkPt4)
источник
Иван Акулов про разработку
3️⃣ Statoscope

statoscope.tech — это как webpack.github.io/analyse, только красивый, развивающийся и с дополнительными фичами.

Мой главный юзкейс:
вызвать webpack --json > stats.json
закинуть файл в Statoscope →
увидеть, почему именно забандлена та самая огромная библиотека.

(Statoscope, кстати, сделал Сергей Мелюков из Яндекса. И у него есть канал @smelukov_dev!)
источник