Библиотека фронтендера | Frontend, JS, JavaScript, React.js, Angular.js, Vue.js
21.6K subscribers
2.89K photos
205 videos
47 files
5.19K links
Все самое полезное для фронтенда в одном канале.

По рекламе: @proglib_adv

Учиться у нас: https://proglib.io/w/77178ed4

Для обратной связи: @proglibrary_feeedback_bot

РКН: https://gosuslugi.ru/snet/67a5b6884689c2151c820bb4
Download Telegram
😸 Разбор задачи

Ранее мы выкладывали задачу для джуна+.

Сегодня разберем, что происходит в этом коде и как работают присваивания и ссылки на объекты в JavaScript.

🔤 Разбор:

1. let a = { n: 1 }; — создаём объект { n: 1 } и присваиваем его переменной a.

2. let b = a; — b теперь ссылается на тот же объект, что и a.

3. a.x = a = { n: 2 };

• Присваиваем новому объекту { n: 2 } переменную a.

• После этого свойству x объекта { n: 2 } присваиваем сам объект { n: 2 }.

4. console.log(a.x); — выводит undefined, так как свойство x в новом объекте { n: 2 } не было установлено.

5. console.log(b.x); — выводит объект { n: 2 }, потому что b ссылается на старый объект { n: 1 }, который теперь имеет свойство x, указывающее на { n: 2 }.

Ответ:

a.x — undefined
b.x — { n: 2 }


🐸 Библиотека фронтендера

#code_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
4😢4
🕹 npm install: хитрость фронтендера

Каждый сталкивался с дилеммой: проверять всё или просто вставить команду и надеяться, что заработает?

Проверяем пакет перед установкой

Копируем команду из StackOverflow и надеемся, что заработает

Голосуем реакциями:

👍 — Осторожность
❤️ — Копипаст

🐸 Библиотека фронтендера

#code_battle
Please open Telegram to view this post
VIEW IN TELEGRAM
25👍15
Каким будет результат

Опрос ниже 🔜

🐸 Библиотека фронтендера

#code_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍1
🧪 Unit-тесты vs QA протестирует

Когда ответственность встречается с делегированием — рождается главный миф разработки.

🟣 Unit-тесты

— Баги находятся на этапе разработки
— Быстрый feedback loop
— Рефакторинг без страха
— Разработчик = ответственность за качество

🟣 QA протестирует

— Быстрее пишу код без тестов
— QA всё равно найдёт баги
— "Я же не тестировщик"
— Баги уходят в прод, но это не моя вина

💭 А в вашей компании есть правило «нет тестов — нет мержа»? Или «работает — не трогай»?

Голосуем реакциями:

👍 — Пишу unit-тесты перед коммитом
❤️ — Тесты есть, но не всегда
🤔 — QA справится, они для этого есть
🔥 — Продакшн и есть тестовая среда

🐸 Библиотека фронтендера

#code_battle
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍9🤔94🥰1
💡 JavaScript-разминка

Что вернёт код на картинке выше ⬆️

Массив вроде есть, но что хранится в array[0]…

🐸 Библиотека фронтендера

#code_battle
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱13🥰5👍1
🤟 Попробовал Vue — и не жалею

Пять лет на React — и вдруг понял, что жизнь без useEffect реально возможна. Ниже — коротко, в чём именно разница 👇

➡️ Реактивность без боли

🟢 React:


const [count, setCount] = useState(0)
setCount(count + 1)


🟢 Vue:


const count = ref(0)
count.value++


Просто работаешь с переменной — и всё обновляется. Никаких setState, никаких магических зависимостей.

➡️ Computed > useMemo

🟢 React:


const filtered = useMemo(() => items.filter(i => i.active), [items])


🟢 Vue:


const filtered = computed(() => items.value.filter(i => i.active))


Во Vue не нужно думать про зависимости — оно само знает, когда пересчитать значение.

➡️ Template против JSX

<div v-for="item in items" :key="item.id"> читается легче, чем {items.map(item => <div>...)}. v-if, v-show, v-model — три директивы, которые убирают сотни строк boilerplate.

➡️ Меньше кода — меньше багов

🟢 React:


useEffect(() => {
if (email && !isValidEmail(email)) setError(‘Invalid’)
else setError(’’)
}, [email])


🟢 Vue:


const email = ref(’’)
const error = computed(() => email.value && !isValidEmail(email.value) ? ‘Invalid’ : ‘’)


Что реально зацепило:

1. Нет useEffect hell — watch и watchEffect проще и читаемее.

2. v-model — двустороннее связывание без боли и бойлерплейта.

3. Меньше бандл: React + ReactDOM ≈ 45 KB (gzip), Vue 3 ≈ 34 KB (gzip).

Что не зашло:

— Экосистема меньше

— TypeScript-интеграция всё ещё местами шероховата

📌 React — мощный фреймворк. Но Vue решает те же задачи проще: меньше бойлерплейта, меньше магии, больше ясности.

На работе продолжаю React (экосистема, команда, легаси). Но когда сажусь за свой проект в выходные — открываю Vue.

🐸 Библиотека фронтендера

#code_battle
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥17🌚5🥰2👏1🎉1
🫥 Как я перестал бороться с TypeScript

После того случая я перестал спорить с TypeScript. Решил внедрить его хотя бы частично — просто чтобы понять, действительно ли он чего-то стоит. И вот тут началось самое интересное.

🧽 На проекте был модуль оплаты. Мелочь: функция принимала price, а я случайно передал туда строку из инпута. JS, конечно, не возмутился — просто сложил две строки:


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 по-другому. Он не просто проверяет типы — он ловит ошибки до того, как они становятся проблемами.

Поначалу раздражает:

«Зачем всё это?»
«Слишком строго!»
«Лишний бойлерплейт!»


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

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

🐸 Библиотека фронтендера

#code_battle
Please open Telegram to view this post
VIEW IN TELEGRAM
🥰103🌚2👍1
📎 5 ESLint-правил, которые реально спасают

1️⃣ eqeqeq — только строгое сравнение

Пример:


if (user.id == “123”) — опасно
if (user.id === “123”) — безопасно


Двойное равенство делает скрытые преобразования типа:


0 == “0” → true


2️⃣ no-implicit-coercion

Пример:


const str = “” + value — неявное приведение
const str = String(value) — явно и понятно


3️⃣ no-unused-vars + no-undef

Ловят опечатки до запуска:


const userName = “Alex”
console.log(usrName) — ESLint сразу найдёт ошибку


4️⃣ no-console


console.log(“ДЕБАГ!!!”, userData)


Если забыть убрать — может утечь чувствительная информация в продакшене

5️⃣ prefer-const


let config = {…} — переменная не переназначается


ESLint подскажет заменить на const

Если нужно — могу сделать версию ещё короче (в один экран).

🔥 Тот же кейс, но с TypeScript


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
Каким будет результат

Опрос ниже 🔜

🐸 Библиотека фронтендера

#code_challenge
Please open Telegram to view this post
VIEW IN TELEGRAM
🥰4🤔2
🔴 История о том, как я убил производительность сайта

Всё началось невинно. Нужен 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. Лучше увидеть проблему сейчас, чем в жалобах пользователей потом.

❗️ P.S. Если твой bundle больше 500 KB — самое время открыть bundle analyzer и посмотреть, что там творится.

🐸 Библиотека фронтендера

#code_battle
Please open Telegram to view this post
VIEW IN TELEGRAM
4🥱3🥰2