Дзевяць пакетаў-інструментаў Node.js, якія варта дадаць прычыму да пачатку напісання коду
Дазвольце дазнаць, як невялікі пакеты Node.js — які включаюць настройкі сяродавыя, перакананне данных, скрыпты, карэстацыю процесаў і логаванне — можу дапамагчы рана выявіць распашчастыя бяги.
Кожны новы проект на Node частаця паводзіцца за адназначным сценарыем: порожняй каталог, адзін файл index.js, і наўмысловая перакананне, што стандартная бібліятэка падкрое большасць таго, што вам трэба. Чырвоныя дні ў роботе прыводзяць да таго, што вы самі пісаеце циклы перапрыбуткі, парсуеце даты за дапамою рэгулярных выразаў і ствараеце ўсё новы, але лягка іншы, чытальнік файлав .env.
У певны момент стае зрозумелым перастаць перазмацаваць вялікія колесы і замест таго скорыцца маленькім, аднак стабільным наборам інструментаў пры пісьме рэальной логікі. Ніякі з гэтых пакетаў не ўражае вялікім функцыоналам. Кожны з іх тыха усунеяе адзін клас багоў, які часта вважаецца нэвыхідным аспектам стварання програмнага забавы. Ціх дзевяць пакетаў варта інсталаваць якомога раней у будзь-ям проекте.
1. dotenv
Якща вы калі-небудзь памылкова дадзілі ключ API у рэпазітарый git, вы вже разумеете прыемнасць гэтага пакета. dotenv чытае пары «ключ-значэнне» з файла .env і запісвае іх у process.env, тады секрэты застаюцца ў файле, які не падлягае кантролю версій, а не ўбудовваюцца безпосередня ў ваш код.
// .env
DATABASE_URL=postgres://localhost:5432/mydb
STRIPE_SECRET_KEY=sk_test_...
// index.js
import "dotenv/config";
const db = connect(process.env.DATABASE_URL);
Это мінімалістычны пакет з вузкай функцыяй, але ён стварае розныню межу тым, калі весь ваша настройка знаходзіцца ў аднам прыемным месцы, і калі яна рассеяна ў кальколькох файлах, а інфармацыя захавана ў старым спілкуванні.
2. zod
Праверкі схемы пад час выконання лёгкае ігнораваць, калі кальколькі оператараў if здаюцца достатнімі для адпаведнага кантролю. Але гэтая впэўненасць зазвычай зникае ў першы раз, калі некоректны запит працягваецца мім гэтых перакрыцчаў і доходзіць да продакшну.
zod дазвае вам адзін раз задаць формат дадзейнаў і на ўсходзе стварыць як верыфікатор пад час выканання, так і адпаведны тип у TypeScript:
import { z } from "zod";
const CreateUserSchema = z.object({
email: z.string().email(),
age: z.number().min(13),
});type CreateUser = z.infer<typeof CreateUserSchema>;app.post("/users", (req, res) => {
const result = CreateUserSchema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({ error: result.error.flatten() });
}
// result.data is now typed and validated
createUser(result.data);
});
Сяродзейныя выгоды паўтараюцца ў моменты, калі да вашай аплікацыі прыходзяць данні: пакеты з API, зменныя сяродавысці, файлы налашчэння і ўсюдзе іншае, што прыходзіць у вашу систему. Перакананне данней на этых пунктах входу значыць, што рэшта вашага коду можа без апасцярыбы прыймаць, што данні, якія ён прымае, маюць адпаведны формат.
3. tsx
Кожны, хто пішае на TypeScript, верагодна страждаў ад додатковых зусібоў, якія выклікае адкрыцце адзінаго скрыпта: кампіляцыя за дапамойкай tsc прычымоў да выканання, або налаштаванне ts-node і чаканне, пакуль ён запускаецца. tsx пачынае ўсё гэта зовсім, выканаючы файлы .ts безпосередна, без жадных крокаў будовы і без неабходнасці налашчэння.
tsx scripts/migrate-users.ts
Ён не прызначан для замены паіплайна стварэння продакшн-версій. Ён створаны для дзесяткаў маленькіх скрыптаў, якія з часам накапліваюцца ў кожнай базе коду — такіх як ексклюзыўныя майграцыі, скрыпты для запуску дадзеных чыстаць або швыдкія пераканальніцы дадзеных. Їм не патрабуецца цэлыя система стварэння проекта; ім проста патрабуецца выкананне практычна мгновэнна, каб не адстаць у роботе чакаючы на компілятор.
4. execa
Вбудованы модуль Node child_process можа выконваць гэту задачу, але для яго правільнага выкарыстоўвання паказваецца ручнае кераванне stdout, stderr, кодамі выходу і адмовамі ў кожны раз. execa аб’еднвае все гэта ў інтарфейс, які працуе так, як вы і спадзяваецеся:
import { execa } from "execa";
const { stdout } = await execa("git", ["rev-parse", "--short", "HEAD"]);
console.log(`Current commit: ${stdout}`);
Падкі выкарыстоўваюцца так, як і трэба, а не працуюць без сігналу пра бяду; выходны тэкст автаматычна адсікаецца, а падтрымка async/await ўжо є вбудованай, не трэба пісаць сабстычны кэпсул для spawn. Для тых, хто стварае інструменты CLI або скрыпты, якія запускаюць іншыя програмы, гэты пакет усунеў цэлы клас багоў, калі ўсё працюе тыха і нічога не выканае, а вам трэба самим здагадвацца прычыну.
5. p-retry
Сеті є ненадзеянымі. API выкананыя ліміты швайнаў. З’язкі з базамі дадзеных іноды перываюцца з прычынамі, якія ніколи не адказваюцца чыста. p-retry абгортае будзь-яю асінхронную функцыю з логікай павторных спроб і экспансіяным адкладэнням, тады ўзрыв адной нестабільной вызоваў не зупініць усі вашы процесы:
import pRetry from "p-retry";
const data = await pRetry(() => fetchFromFlakyApi(url), {
retries: 5,
onFailedAttempt: (error) => {
console.log(`Attempt ${error.attemptNumber} failed. Retrying...`);
},
});
Часта ситуацыя, калі для кожнага проекта давайся працаваць з такой логікай вручную, чыясць з адміністрацыяйіямі, і часта працаваць без належных механізмаў адкладэння, што можа ўсё больш навантажваць проблемную API за дапамогою швыдкіх праказаў. Шэрыкатура правільна рашае гэту проблему за лічбу ліній коду, і яна запярэдзіла таму, каб аднаго з інтеграцыйных рашэнняў не выйшло з працы пад час звычайнага перыву ў работе трэцяй стороны.
6. day.js
Работа з датамі ў чыстам JavaScript є вельмі некомфортной, а moment.js, бібліятэка, якую большасць людзей выбірала як стандартную, є важкай у викорыстоўванні і больш не развиваецца. day.js прыносіць падобна зручную API, але з набагато меньшым розміром:
import dayjs from "dayjs";
const deadline = dayjs().add(3, "day").format("YYYY-MM-DD");
const isOverdue = dayjs(invoice.dueDate).isBefore(dayjs());
Фарматаванне дат, ўпорыленне іх, аднараджэнне чы скасыванне працэвакуў часу, а таксама парсаванне заплутаных страк дат стаюць простымі, што значыць, ўжо не будзе тых тонкіх багоў, якія выйшлі з ручнага выкарыстоўвання такой арыфметыкі.
7. pino
console.log добра падходзіць для маленькіх скрыптав, але калі вы запускаеце сервіс у працэўным режыме, які стварае тыячы запісаў логаў за хвіліну, вам патрэбна система, якая магла б фільтруваць і шукаць інфармацыю. pino выдае структураваныя JSON-логі з такой швалёнасцю, якая практычна не вплывае на вашу аплікацыю:
import pino from "pino";
const logger = pino();
logger.info({ userId: user.id, action: "checkout" }, "Order placed");
Паколькі выходны даны ў структураванама формате, будзь-які інструмент, які вы вжываеце для ўзьяць іх, — Datadog, стак ELK чы нават проста grep-ванне файла пазней, — можа правільна ўзрабатваць і фільтруваць іх. Гэта краща, чым прасувацца праз сторунки звычайнага тексту, намагаючыся знайсці тую ўзначальную лінію, калі вось-вось ўсё загорэцца.
8. cheerio
Інодзе ўсё, што вам трэба, — это выявіць частку структураваных дадзеных з HTML-сторунки, і запуск цэлага браузера без вікна здаецца чыстай перэдозаваннем для задачі, якая на самае справа ўсьмо «знайсці гэты элемент і прачытаць його тэкст». cheerio задае API, схожы на jQuery, для узрабатвання та запитоў HTML з боку сервера, без жадных витатаў, якія супакоюе запуск рэальнага браузера:
import * as cheerio from "cheerio";
const $ = cheerio.load(html);
const titles = $("h2.product-title")
.map((_, el) => $(el).text().trim())
.get();
Ён не выконвае JavaScript на стороне веб-старонкі, таму не можа заменіць такі інструменты, як Playwright, калі контэнт адрасаваецца на стороне кліента. Але для адгружвання статычнага маркапу, працы з контэнтам, падобным фідам, або выкарыстоўвання значэнняў з старонак, якімі вы керуеце, ён значна быстрей і легкій, чым запуск экзанпляра браузера.
9. pm2
Запуск вашай аплікацыі за дапамою node index.js ўсё гаразд, пакуль яна не зламаецца сярод ночы і ніхто яе не перзапускае. pm2 працуе над тым, каб ваш процес продовжваў працаваць, автаматычна перзапускае яго пасля зламу і апранае базавую наглядоўную функцыю і карэткаванне логаў, усё гэта без патрэбы ў цэлай платформе для кантейнеровых оркестрацый.
pm2 start index.js --name my-api
pm2 logs my-api
pm2 restart my-api
Для багаторох малых і середніх систем така праця з наглядам за процесам ёсць усім, што вам патрэбна. Яе нельга выкорыстоўваць замест Kubernetes, калі вы керуеце вялікай распраўленай системай, але на аднам серверы, дзе запускаецца калькі процэсав Node, гэта разліка межу тым, калі паказаецца нешта і трэба ўсё час заходзіць праз SSH, і тым, калі такой проблэмы вообща няма.
Асалодны мэт
Ніякі з эўсёх дзевяць пакетаў самі по сабе не ёсць выключна прыгожымі, і гэта насправдзе ўсё, што важна запамятаць. Кожны з іх берае на сябе частку логіки, якую інакш давэрыў быся напісаць сам, зазвычай трохі памыліўшыся ў першой спробе, а пасля мусіць падтрымвацца без канца. Вжыванне такіх пакетаў — гэта не спроба зашчадзіць час. Гэта спосаб прыкладзіць вашы обмежаныя зусілля да тых частак прыемлена, якія справа ў вас, каб іх створыць, а не перапісваць і знову дыбагаваць циклы для пятага проекту.
Спадневаная літэратура
- Функцыі Node.js 26, якія таямніча заменяюць гады рашэнняў — аптака API Temporal у Node.js 26, виконанне TypeScript на роўні языка, дапаможнікі кэшаў і іншыя дадатакі, якія усунулі давга існуючыя альтернатывы.