Node.js Recipes
2.37K subscribers
91 photos
1 file
420 links
По буднях нотатки по #Nodejs розробці, по вихідним огляди конференцій та доповідей (с) @galkin_nikita
Співробітництво https://telegra.ph/node-recipes-01-19
Download Telegram
Цього місяця пройде Node Congress 2023. Його роблять хлопці з GitNation. Якість доповідей на минулих конференціях можна оцінити на їхньому порталі. Конференція пройде в Берліні та онлайн. 32 доповідача, включаючи Раяна Даля. 9 воркшопів з яких 3 безкоштовні.

Посилання:
🔗 nodecongress.com
🔗 portal.gitnation.org
Не соромно виправляти неполадки за допомогою console.log замість debug-mode. Шкода не знати про console.trace. Використовуйте console.trace, щоб зрозуміти, звідки викликається ваш код.
Як швидко перейти на return await?
#eslint #typescript

Спочатку коротко розповім, навіщо це робити. Помилки в логах записуються у stack trace. Якщо функція повертає not resolved promise, то у stack trace буде дірка. Приклади коду та докладний розбір є у Node.js Best Practices 2.12 Always await promises before returning to avoid a partial stacktrace

Минулого тижня я занурився у debugging. Проблема була замаскована обірваними stack trace. Виявляється, що позбутися цього можна дуже швидко. Достатньо додати @typescript-eslint/return-await . Він має автофікс! Після eslint --fix дебаг втратив детективний сюжет, бо стало очевидним, що проблема у відсутності транзакцій на рівні бази даних. Так що додайте це правило до вашого проекту, щоб наступне налагодження пройшло швидше.
Використовуйте правильну термінологію!
Node.js – це середовище виконання JavaScript (runtime environment). Не фреймворк, не двигун, не бібліотека, а саме runtime!
Нещодавно один з моїх колег, з яким ми не спілкувалися протягом 3-х років, написав мені. Два року тому колега виконав тестове завдання, яке полягало в створенні одного специфічного фронтенд компонента. Він навіть отримав за це офер, але так і не прийняв його. До кінця минулого року компонент був опублікований тільки в його особистому GitHub профайлі, а потім він змінив видимість репозиторія з публічної на приватну.

Після Нового року йому написали: "Друже, а чому ти видалив свій пакет? У нас зараз проект не збирається." Колега повернув все назад, ввічливо поцікавився, чи працює тепер все так, як має. Наступного листа він спитав як зв'язатися з адвокатом компанії.

Справа в тому, що під час спільної роботи я пояснив йому, як працює ліцензії і підказав npm config set init-license="UNLICENSED". Листування з інженером було достатньою доказовою базою того, що компонент використовувався без його дозволу.

Листування з адвокатом та СТО показало, що компанії не вела і не аналізувала SBOM (software bill of materials). Помилку визнали без суду. У березні компанія впровадила SBOM. А на початку квітня колега передав компонент та права на нього, підписав NDA та й отримав від них виплату!
Як додати у PostgreSQL тернарний оператор?
#db

TL;DR; додайте замість тернарника збережену процедура iif

PostgreSQL має дуже обмежену функціональність для умовних виразів (Conditional Expressions):
CASE дуже схожий на switch case
COALESCE, що повертає перший зі своїх аргументів, який не є нульовим
NULLIF повертає null, якщо значення дорівнює одне іншому; інакше повертає перше значення.
GREATEST/LEAST повертає найбільше/найменше значення

Тернарного оператора немає, його заміна за допомогою CASE виглядає так:
CASE WHEN condition THEN true_result ELSE false_result END
Багатослівно, та й ще важко знаходити помилки коли використовуються різні типи даних. Це типова проблема на проектах з LowCode admin UI (наприклад retool) чи LowCode Analytics (наприклад Looker Studio).

Для спрощення я додаю збережену процедура:
CREATE or replace FUNCTION iIF(
condition boolean, -- IF condition
true_result anyelement, -- THEN
false_result anyelement -- ELSE
) RETURNS anyelement AS $f$
SELECT CASE WHEN condition THEN true_result ELSE false_result END
$f$ LANGUAGE SQL IMMUTABLE;

Після цього можна використовувати
iff(condition, true_result, false_result)

Читати та підтримувати це простіше. Особливо аналітикам, які звикли до Google Sheets.

⚠️Традиційне застереження⚠️ не використовує збережені процедури для бізнес-логіки, бо це розмазує її реалізацію між Node.js кодом та кодом збережених процедур.
Node.js 18.16
#release

Цього тижня вийшов мінорний реліз Node.js 18.16. Він включає:
👉 початкова підтримка компіляції JavaScript в виконувану програму (single standalone executable). Поки що лише для одного файлу, при цьому копіює весь бінарник Node.js, а значить це не кроссплатформенно. Для мене виглядає як спроба зробити silver bullet. Щоб створити власну думку, ви можете переглянути документацію репозиторію nodejs/single-executable
👉 новий url parser Ada. Нагадаю, що Node.js та браузери використовують однакову сигнатуру для класу URL, але мають різну реалізацію. Node.js документація, браузерна документація. ⚠️ Рекомендую перечитати браузерну документацію. Особисто я упустив, що в конструктор можна передавати другий аргумент base. Так ось новий парсер швидший і написаний на чистому сучасному C++. У наступному релізі ноди, можна чекати на його оновлення на 2-у версію. Детальніше у пості автора.
👉 експериментальні методи AsyncLocalStorage.bind та AsyncLocalStorage.snapshot, для яких я не розумію застосування.

повний список змін у changelog
Як працює watch-mode у NestJS?
#nestjs

Під час розробки NestJS прийнято запускати у watch-mode (live-reload). Приклад:
"scripts": {
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch"
}

У цьому режимі NestJS cli стежить за зміною ts файлів і перезапускає ваш додаток. У nest-cli.json є compilerOptions, який визначає що буде використовуватися для цього – webpack або tsc. У цьому файлі можна визначити watchAssets та перелік не ts файлів assets, при зміни яких необхідно перезапускати додаток. Приклади використання:
– MVC, тобто html-рендерінг.
– email-templates
– .env файл

Детальніше про налаштування NestJS cli у документації.

На завершення кілька цікавостей:
1️⃣ У watch-mode iснує відома проблема нескінченного циклу "File change detected" у Windows-користувачів з TypeScript 4.9+. Рішення у FAQ.
2️⃣ У @nestjs/cli v9.4, яка вийшла минулого тижня, додали manual-restart-watchmode. Про це свідчить напис To restart at any time, enter rs
Ноді вже понад 10 років. Для усвідомленого формування стратегії розвитку на наступні десяток років проводять опитування. Пропоную вам взяти у ньому участь:
👉 https://hubs.la/Q01LHCBD0.

Результати опитування будуть використовуватись командою next-10. Їхня робота документується в однойменному репозиторії. Там можна знайти звіти та відео з нарад. Ось наприклад звіт з опитуванням за 2021 рік.
Як не втрачати stack trace?
#nodejs_api

Сьогодні ми обговоримо, що робити з помилками, у яких stack trace закінчується at processTicksAndRejections (node:internal/process/task_queues)

Багато популярних пакетів викидають помилки таким чином, що stack trace обривається у коді самого пакета. Це ускладнює відлагодження таких виключень, оскільки втрачається стек викликів у коду додатка. Нажаль, у багатьох випадках контрибутори пакетів відхиляють запити на виправлення цієї проблеми. Приклади:
- Improve axios stack traces axios/axios#2387
- Missing stack trace on errors stripe/stripe-node#1066

Якщо пакет популярний, то ком'юніті запропонує якісь рішення. Наприклад axios-better-stacktrace.

Загальним рішенням є використання try-catch та викидати нову помилки з cause. Нагадую, що ми маємо Error: cause з Node v16.9.0. Для цього я використовую такий хелпер:

export function reThrow(reason: unknown, errorConstructor: ErrorConstructor = Error): never {
const errorMessage = reason instanceof Error ? reason.message : errorConstructor.name;
const error = new errorConstructor(errorMessage, { cause: reason });
Error.captureStackTrace(error, reThrow);
throw error;
}

Error.captureStackTrace(... видаляє з stack trace рядки хелпера.

Приклад використання:
const session = await stripeClient.billingPortal.sessions.create({customer: ''}).catch(reThrow);
#typescript

На вихідних вийшла нова версія VSCode розширення pretty-ts-errors. Воно додає до вашого редактора:
👉 підсвічування синтаксису для типів у повідомленнях про помилки
👉 кнопка, яка відкриває оголошення відповідного типу поруч з типом у повідомленні про помилку.
👉 кнопка, яка відкриває помилку на typescript.tv
👉 кнопка, яка відкриває помилку на ts-error-translator

Якщо ви ще не користуєтеся цим розширенням, рекомендую встановити. pretty-ts-errors дуже спрощує роботу джунів та їх менторів.

Автор просить підтримати лайками додавання до VSCode необхідного API. Якщо ви віддаєте перевагу WebStorm, то ставте лайк JetBrains support. Будь ласка, ⚠️використовуйте лайк, а не коментарі⚠️ – це дозволить робити правильні метрики без спам сповіщень через коментар.

Посилання
🔗 source code
🔗 VSCode marketplace
🔗 upvotes to move forward
TDD це не догма, а процес розробки. А який у вас процес?
#npm

Щоразу, коли я роблю аудит і бачу у package.json:
"test": "echo 'not implemented yet'"
я запитую одне й те саме питання, а чому у вас існує саме такий test скрипт? Не залежно від відповіді наступне питання завжди одне й те саме, яке винесене в заголовок. Подальше обговорення у 95% випадків показує, що в цьому конкретно репозиторії на тести немає часу/необхідності. А та ще за CI/CD відповідає інша команда, яка не знає про прапор --if-present.

Будь-який неоголошений скрипт із цим прапором не буде провалений. Тому, якщо ви виконуєте функцію техлід або DevOps інженера на проекті, то використовуйте де необхідно npm run test --if-present.

Ще нагадаю, що не кожен проект потребує юніт тестів, що лежать в основі TDD. Але кожен проект вимагає здорового глузду та знання використовуваних інструментів. Тож перечитайте документацію npm, node та вашого фреймворку.
Як уникнути Race Conditions у JavaScript коді?
#worth_seeing

Цього тижня з консалтингу був цікавий баг. Проблему ілюструє такий код:
import { scheduler } from 'node:timers/promises';

async function countLikes() {
const postIds = [1, 2, 3];
let likes = 0;
await Promise.all(
postIds.map(async (id) => {
likes += await fetchLikes(id);
})
);
return likes;
}

async function fetchLikes(id: number) {
await scheduler.wait(Math.random() * 1000);
return id;
}
Очікуваний результат виконання функції countLikes це 6, але в коді є Race Condition. Щоб його виправити необхідно замінити likes += await fetchLikes(id) на
const count = await fetchLikes(id);
likes += count;

Щоб уникати таких випадків існує eslint правило require-atomic-updates. Воно за замовчуванням вимкнено у eslint:recommended . Як правило воно надто суворе, оскільки змушує писати код у Defensive programming style. Особисто мені це не зручно, тому я тримаю його вимкненим, але час від часу вмикаю його, щоб переглянути ризиковані місця.

Академічно правильний спосіб боротьби з Race Conditions є у доповіді Тимура Шемседінова Web Locks API in Node.js and browser.
Прямо зараз почалися два стрими:
👀 https://www.youtube.com/watch?v=EbqxKNW6Hpk
ТЕРЕВЕНІ Сергія Бабіча @toisamyibabich з Віктором Турським @jabascript

👀 https://www.youtube.com/watch?v=PB0rXYyEeP0
JavaScript балачки #9 від Іллі Клімова @jsninja_news
Для аргументованої дискусії потрібні як докази, так й дані. Коли йдеться про браузери, протоколи, тощо, я використовую Cloudflare Radar. Сервіс малює чудову інфографіку, можна фільтрувати по конкретній країні, ще він надає безкоштовний апі.
10 пакетів, які не повинні бути у вашому списку залежностей у 2023 році

async ➡️ async/await
aws-sdk ➡️ @aws-sdk/v3
bluebird ➡️ native promise
config ➡️ 12 factor app
graphql-upload ➡️ presigned URL
memoizee ➡️ cache in redis
moment ➡️ well known legacy
pm2 ➡️ docker
request ➡️ well known legacy
uuid ➡️ crypto.randomUUID()

всі вони морально застаріли та суперечать сучасним принципам Node.js розробки.
Forwarded from GDG Cloud Kyiv (Nikita)
Наступного тижня буде Google I/O 2023. Це онлайн конференція, де Google представляє свої нові продукти та технології для Web, Mobile, Cloud, AI.
У зв'язку з цим у нас два заходи:
10 травня – Google I/O 2023 Watch Party at Discord, спільний захід з GDCS KPI у їхньому discord каналі. Координатор заходу – Kateryno Hrytsaienko.
11 травня – Google I/O 2023 Watch Party at Youtube, прямий ефір на YouTube у якому Нікіта Галкін та Віктор Турський обговорять новинки та дадуть відповіді на запитання ком'юніті.
Forwarded from GDG Cloud Kyiv (Nikita)
тим часом Віктор робить фінальне налаштування. Починаємо за 15 хвилин! 🚀
👀 https://youtu.be/watch?v=Zq-Pv4g3JC4
У багатьох інструментів є не лише логотип, але й маскот, тобто талісман-тварина. Наприклад, маскотом докера є синій кит з контейнерами.

А ви знаєте, що маскотом #npm є вомбат? Proof
На ілюстраціях він часто грає з кубиками npm пакетів.

Ввечері п'ятниці я задаюся питанням, чи знав дизайнер, який придумав цього маскота?.. а чи знав той, хто затвердив цю айдентику?.. Чи знали вони, що кишечник вомбата влаштований таким чином, що він какає кубиками? Proof

Рецепт про те, як я оновлюю кубики вже наступного тижня. Всім гарних вихідних.
Мій друг хоче увійти до IT, що йому порадити?

Для успішної роботи в IT обов'язковою умовою є систематична самоосвіта. Тому не варто радити:
– йти на курси
– шукати ментора
– вступати в ком'юніті "Вчимо <технологія> разом"
– боротися за місце в інтернатурі
– підписуватись на ваш улюблений ютуб канал

Ці поради не працюють, якщо людина не має навички самоосвіти. А що тоді працює? Допомога у підборі матеріалів для самоосвіти. Ось де я зазвичай підбираю матеріали для початківців:
- https://www.freecodecamp.org/learn/
- https://exercism.org/tracks
- https://www.coursera.org/courses (пам'ятаємо про фінансову допомогу)

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

90+% людей не закінчать свого першого курсу. Це нормально, усі люди різні. IT і регулярне самоосвіта не підходять усім. Але тим, хто закінчить, можна радити курси, менторів або навіть рефералити в інтернатуру вашої компанії.