Ditsmod — новий TypeScript веб-фреймворк для Node.js
Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.
Ditsmod є Node.js веб-фреймворком, його назва складається із DI + TS + Mod, щоб підкреслити важливі складові:
він має Dependency Injection, написаний на TypeScript, та спроектований для хорошої Modularity (тобто модульності).
- Зручний механізм указання та вирішення залежностей між різними класами застосунку: ви в конструкторі указуєте інстанси яких класів вам потрібні, а DI бере на себе непросту задачу «де їх взяти».
- Можливість легко підмінювати by default класи в ядрі Ditsmod своїми власними класами. Наприклад, швидше за все, ви захочете підмінити клас логера на ваш власний клас, оскільки by default логер записує логи лише в консоль.
- Можливість легко підмінювати класи вашого застосунку тестовими класами (mocks, stubs), не змінюючи при цьому код вашого застосунку. Це дуже суттєво спрощує тестування.
- Ditsmod спроектований, щоб забезпечувати хорошу модульність всього застосунку, а отже і хорошу масштабованість. Його DI підтримує ієрархію, а це означає, що ви можете оголошувати одинаків: або на рівні усього застосунку, або на рівні конкретного модуля, або на рівні HTTP-запиту.
Ті, хто знайомий з Angular, помітить, що деякі концепції архітектури цього фреймворка дуже схожі на Angular концепції. Це справді так, більше того — сам DI фактично витягнутий з Angular v4.4.7. (з мінімальними допрацюваннями) та інтегрований в Ditsmod.
Мотивація для створення Ditsmod
Рідний Node.js веб-сервер надає мінімальну функціональність для прийому HTTP-запитів та відправки HTTP-відповідей. Він не надає систем роутінгу, парсингу тіла запиту, логування, обробки помилок, тестування. І оскільки в реальних застосунках уся перерахована функціональність є базовою, виникає потреба у додатковому веб-фреймворку. З іншого боку, уся перерахована базова функціональність є майже у будь-якого Node.js веб-фреймворка, але це ще нічого не говорить про зручність його використання.
Огляд ExpressJS та KoaJS
Давайте глянемо на зручність використання, наприклад, ExpressJS та KoaJS. Вони використовують дуже мало коду для «Hello, world!», але в реальних застосунках нам треба вирішувати значно складніші завдання, розподіляючи наш код на десятки чи навіть й на сотні файлів. Архітектура даних фреймворків формувалась задовго до виходу ES2015, тоді вони вирішували проблему «callback hell» за допомогою створення послідовного ланцюжка викликів так званих middleware, і в кожному із них повинен був викликатись наступний middleware, посилання на який, частіше за все, передавалось у змінну із назвою next
.
Таким чином, можна сказати, що головна особливість архітектури цих фреймворків була актуальною до виходу ES2015, коли у JavaScript з’явились Promise
та класи. Хоча виходили в реліз ES2015, ES2016, ES2017... майже нічого не змінилось в архітектурі ExpressJS, а у KoaJS 2 додались нові фічі із функціями-генераторами, із функціональністю async/await, із додаванням об’єкту контекста. Але все одно стара архітектура із послідовним ланцюжком викликів middleware нікуди не зникла. В плані модульності теж майже нічого не змінилось, окрім хіба що нового способу експорту/імпорту JavaScript модулів, але стара проблема з упорядкуванням структури проекта не зникла.
Як говориться у туторіалі на developer.mozilla.org, ExpressJS дуже мінімалістичний і гнучкий фреймворк, але це часто й ускладнює створення правильної структури проекту:
While Express itself is fairly minimalist, developers have created compatible middleware packages to address almost any web development problem. There are libraries to work with cookies, sessions, user logins, URL parameters, POST data, security headers, and many more. You can find a list of middleware packages maintained by the Express team at Express Middleware (along with a list of some popular 3rd party packages).This flexibility is a double edged sword. There are middleware packages to address almost any problem or requirement, but working out the right packages to use can sometimes be a challenge. There is also no «right way» to structure an application, and many examples you might find on the Internet are not optimal, or only show a small part of what you need to do in order to develop a web application.
Судячи із постів на різних блогах, ExpressJS та KoaJS використовують майже завжди на малих проектах, а також для мікросервісів, де якраз кожен «мікросервіс» сам по собі являється малим застосунком.
Огляд NestJS
TypeScript вніс у світ JavaScript, можна сказати без перебільшення, революційні можливості для зручності написання коду в IDE, можливості для дуже суттєвого зменшення кількості помилок, а отже — проекти написані на TypeScript можна робити значно більшими.
На даний момент є досить популярний веб-фреймворк написаний на TypeScript — це NestJS. Перший стабільний його реліз був в кінці 2017 року, тобто вже після виходу ES2015, ES2016, ES2017. Його автор дуже активно розвиває своє дітище, а тижнева кількість скачувань із npmjs.com складає вже майже 500 тис. і продовжує стабільно рости.
Видно що автор NestJS дуже старанно намагається додати до цього фреймворка усе саме сучасне і
прогресивне. Справді, NestJS:
- має власний CLI
- має велику кількість декораторів для різних потреб
- впроваджено багато фіч, дуже схожих на Angular фічі: Dependency Injection, провайдери, модулі,
pipes, guards, interceptors, lifecycle events... - має підтримку TypeORM
- має підтримку OpenAPI
- має підтримку GraphQL
- має підтримку Websockets
- має рекомендації для використання мікросервісів
- ...
Так чому ж, знаючи про NestJS, виникла потреба у створенні Ditsmod? Головною причиною була моя суб’єктивна оцінка NestJS, мені здалось що можна написати веб-фреймворк із простішим API але, разом із тим, зробити його більш потужнішим як в плані продуктивності, так і в плані масштабованості.
Огляд Ditsmod
Хоча Ditsmod у своєму ядрі має код для підтримки хорошої модульності застосунку, бенчмарки з Hello World показують, що він є навіть швидшим за один із найпопулярніших та найлегших фреймворків — за Koa v2:
На цій діаграмі бенчмарку з Hello World, самим швидшим є Fastify. Але, як сказано у його документації — Fastify навіть швидший за рідний Node.js вебсервер. Як таке може бути? — Відповідь на це запитання мені не відома, але відомо, що стабільна версія цього фреймворку вийшла в реліз більше 4 років назад, а він чомусь не має великого кута нахилу кривої популярності (судячи зі статистики скачування). Можливо заточеність цього фреймворку саме на швидкості має побічні ефекти у вигляді незручності використання, мені не відомо.
Другим по швидкості йде NestJS на платформі Fastify. Але дивно, що таке поєднання не є супер популярним, адже якщо порівнювати це зі статистикою скачування NestJS на платформі ExpressJS, то виявиться, що їх рахунок 9:1 на користь NestJS + ExpressJS. І це при тому, що NestJS + ExpressJS є самим повільним варіантом (див. останній стовпчик на діаграмі). Звичайно ж, тут має місце вплив популярності самого ExpressJS, але ж NestJS позиціонується як Platform agnosticism (тобто, в теорії, можна писати код у NestJS не залежно від платформи фреймворку, на базі якої він працює). Швидше за все, заявлений «Platform agnosticism» не працює на практиці так, як було задумано в теорії.
Код із даними бенчмарками ви можете знайти у цьому репозиторії.
Більш детально познайомитись з Ditsmod.
46 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів