После того случая я перестал спорить с TypeScript. Решил внедрить его хотя бы частично — просто чтобы понять, действительно ли он чего-то стоит. И вот тут началось самое интересное.
function calcTotal(price) {
return price + 2000
}
calcTotal("4000") // "40002000»
На проде чек вырос в два раза, клиент — в гневе. А я — с новыми седыми волосами.
С TypeScript такого бы не случилось:
function calcTotal(price: number) {
return price + 2000
}
// Argument of type 'string' is not assignable to parameter of type 'number’
После этого я посмотрел на TS по-другому. Он не просто проверяет типы — он ловит ошибки до того, как они становятся проблемами.
Поначалу раздражает:
«Зачем всё это?»
«Слишком строго!»
«Лишний бойлерплейт!»
А потом замечаешь: автодополнение стало умнее, рефакторинг — безопаснее, новые разработчики быстрее разбираются в коде.
#code_battle
Please open Telegram to view this post
VIEW IN TELEGRAM
🥰10❤3🌚2👍1👏1
Пример:
if (user.id == “123”) — опасно
if (user.id === “123”) — безопасно
Двойное равенство делает скрытые преобразования типа:
0 == “0” → true
Пример:
const str = “” + value — неявное приведение
const str = String(value) — явно и понятно
Ловят опечатки до запуска:
const userName = “Alex”
console.log(usrName) — ESLint сразу найдёт ошибку
console.log(“ДЕБАГ!!!”, userData)
Если забыть убрать — может утечь чувствительная информация в продакшене
let config = {…} — переменная не переназначается
ESLint подскажет заменить на const
Если нужно — могу сделать версию ещё короче (в один экран).
function processPayment(amount: number) {
api.charge(amount)
}
processPayment(«100»)
// string is not assignable to number
P.S. Если не готовы к TS — начните хотя бы с этих 5 правил.
#code_battle
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍2🌚2🥰1
Всё началось невинно. Нужен debounce для поиска — поставил Lodash. Нужно форматировать даты — Moment.js. Иконки? React Icons, конечно.
Через три месяца разработки делаю
npm run build и вижу:⚠️ 2.8 MB main.js
Решил разобраться. Установил webpack-bundle-analyzer и офигел от того, что увидел.
Оказалось, я тащил в проект кучу лишнего:
Lodash (70 KB)
Импортировал всю библиотеку ради двух функций. Остальные 200+ методов просто висят мёртвым грузом.
Moment.js (70 KB)
Мне нужен был толькоformat('DD.MM.YYYY'), а получил все локали мира, парсеры timezone и calendar-системы.
React Icons
По проекту набралось 50+ импортов разных иконок. Bundle незаметно разросся.
Картинки в bundle
Webpack превращал изображения в base64 и пихал прямо в JavaScript. Hero-картинка на 200 KB стала частью main.js.
Начал с простого — заменил импорты на точечные:
// Было: тащит 70 KB
import _ from 'lodash'
// Стало: всего 1-2 KB
import debounce from 'lodash/debounce'
Дальше пошёл по библиотекам и нашёл более лёгкие альтернативы:
Moment.js (70 KB) → date-fns (11 KB)
Axios (13 KB) → fetch API (нативно)
Для роутинга включил code splitting. Теперь страницы грузятся только когда пользователь на них переходит:
const Dashboard = lazy(() => import('./Dashboard'))
const Settings = lazy(() => import('./Settings'))
<Suspense fallback={<Loader />}>
<Dashboard />
</Suspense>
С картинками разобрался так: большие файлы переложил в
/public, конвертнул в WebP (экономия 30-50%), добавил loading="lazy".И последнее — настроил size-limit в CI/CD. Теперь если кто-то попытается влить PR с раздутым bundle, пайплайн упадёт:
"size-limit": [{
"path": "build/static/js/*.js",
"limit": "500 KB"
}]
Было:
• Bundle: 2.8 MB
• Загрузка на 3G: 8.5 секунд
• Lighthouse: 45/100
Стало:
• Main bundle: 380 KB
• Остальное в lazy chunks по 50-150 KB
• Загрузка на 3G: 1.2 секунды
• Lighthouse: 92/100
Сайт стал грузиться в 7 раз быстрее. Пользователи перестали жаловаться. Менеджер доволен.
Главная ошибка была в подходе. Я думал: «npm install — и готово, пакеты же для этого и есть!»
Но каждый килобайт в bundle — это реальное время загрузки. Особенно для людей не на оптоволокне.
У меня на MacBook сайт грузился моментально. А у пользователя с iPhone 8 в метро на 3G — 10 секунд чёрного экрана. Это разные миры.
Теперь перед каждым
npm install спрашиваю себя: мне правда нужна вся библиотека? Или хватит одной функции? Может, это вообще можно сделать нативно?И раз в спринт запускаю
npm run build && npm run analyze. Лучше увидеть проблему сейчас, чем в жалобах пользователей потом.#code_battle
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9🥱4🥰2🔥1
Любой styled-компонент генерирует классы, хеши, вставляет
<style> в документ.Это не бесплатно: инъекция стилей и работа GC заметны на слабых устройствах. На MacBook незаметно, на бюджетных Android — уже да.
const Button = styled.button`
background: ${p => (p.primary ? 'blue' : 'gray')};
`;
Инспектор показывает:
.css-4kq0lj { margin: 0 auto; }
И теперь ищи, какой из 50 вложенных styled-компонентов это создал.
Небольшое отличие порядка импортов — и хеши на сервере и клиенте расходятся. Гидратация падает, юзер видит FOUC. С этим сталкивался почти каждый.
CSS Variables, CSS Modules, Container Queries покрывают 90% кейсов CSS-in-JS:
• Никакого рантайма
• Никаких хешей
• Никакого лишнего веса в бандле
• Прозрачный дебаг
.button {
background: var(--primary-color);
}
Динамика? Меняем
--primary-color из JS → браузер обновляет мгновенно.#code_battle
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍6