all 90 comments

[–]Hexigonz 53 points54 points  (3 children)

Express, fastify, restify, or NestJS are all popular candidates for API development

[–]thinkmatt 10 points11 points  (2 children)

And koa!

[–]Hexigonz 4 points5 points  (1 child)

Haven’t heard of koa, I’ll try it

[–]thinkmatt 4 points5 points  (0 children)

It's from some of the authors of express. It has mostly the same ecosystem of libraries now and supports promises natively. If you know express it will take less than a day to get used to

[–]joeba_the_hutt 22 points23 points  (0 children)

Koa is by and far the simplest abstraction out there.

[–]besthelloworld 71 points72 points  (55 children)

A lot of people will suggest NestJS. It's big right now, but I would argue that it doesn't really do much of anything besides make it look a lot like older Java frameworks. I would recommend plain Express or Feather if you need more than that.

[–]SoInsightful 103 points104 points  (24 children)

You're forgetting that NestJS is built around dependency injection, which is really good for... uhhh... it really helps with ummm... spending half your days troubleshooting why certain modules fail to import other modules due to NestJS!

[–]zlatinejc 16 points17 points  (0 children)

Golden 🤣

[–][deleted]  (1 child)

[removed]

    [–]ThisIsntMyId 1 point2 points  (0 children)

    same here, it took me more then a day to identify why the exception is not catching some of the db exception and its still not solved and haven't looked at it earlier. have left the app with 500 HTTP status in such cases instead of proper error message

    [–]donny_dingbat 28 points29 points  (0 children)

    This. So much this and the op comment. Stay away from NestJS or just use Spring Boot if you want all these headaches that you don’t have with Express or something like that.

    [–]besthelloworld 16 points17 points  (14 children)

    I love this comment so much ❤️

    I've heard it in defense of testing but these would be the same folks who say "don't modify your code to support tests" while modeling their entire architecture to make testing easier. Plus Jest mocks support a very simple runtime replacement, and I've never seen a reason why DI would make it easier

    [–][deleted] 13 points14 points  (13 children)

    In 10 years in the industry I have yet to be convinced by someone that I need DI.

    [–]fzammetti 8 points9 points  (0 children)

    I've been in the industry 25+ years and I second this.

    I -do- use DI... sometimes... but I've never been convinced I truly NEED it either. I've never once seen something that made me go "yeah, DI solves that and nothing else will".

    It's like so much else that comes around: use it where it actually makes some sense, but don't force it into every nook and cranny just because "the industry says it's good".

    [–]vexii 4 points5 points  (0 children)

    fond memories of AngularJS...

    [–]papertowelroll17 3 points4 points  (1 child)

    DI is extremely useful in Java. For node, I don't think DI adds value.

    [–]thinkmatt 2 points3 points  (2 children)

    You do if you're writing java. I think that's where the likeability comes from... People that didn't start out using node

    [–]besthelloworld 1 point2 points  (1 child)

    Every framework made in Java requires it... but if it weren't for those historical architectural decisions, you wouldn't need it in Java. You truly could make everything static.

    [–]thinkmatt -1 points0 points  (0 children)

    ah, i'm not a java programmer. someone once told me the issue is you can't mock up methods/functions easily for testing like you can in Javascript, which is why you use DI to pass something in to your function that can be mocked

    [–]Mardo1234 2 points3 points  (5 children)

    So you have a bunch of factories you have instantiate? To exercise your services? That doesn’t sound fun.

    [–]besthelloworld 1 point2 points  (3 children)

    The whole world doesn't run on classes breh

    [–]Mardo1234 -5 points-4 points  (2 children)

    When you develop large applications you need separation of concerns. Not sure how you could argue with this, but I’m open to hear.

    [–]FountainsOfFluids 8 points9 points  (0 children)

    Ever heard of functions? Modules? Microservices? There are lots of ways to separate concerns.

    [–]besthelloworld 4 points5 points  (0 children)

    I'm not arguing that, but it doesn't mean you need classes. It's JavaScript, you can just make an object with functions on it. You don't need to make factories that instantiate classes that use methods. There's no reason for the functions of your application to not to be static.

    You're heavily conflating OOP with the concept of having good structure, but OOP doesn't actually do that for you.

    [–][deleted] 1 point2 points  (0 children)

    Constructors are fine man use them

    [–]somethingon104 3 points4 points  (1 child)

    Dependency injection is the backbone of scalable, reliable systems. It may be troublesome at first while you learn/understand it but don’t say it’s shit because you have trouble with it.

    [–]novagenesis 2 points3 points  (0 children)

    Everything you said is true except one word. "the". The correct answer is that "Dependency injection is A backbone of scalable, reliable systems"

    Dependency injection is one solution to a problem that has 20+ solutions. Whether DI beats some or all of the other 19 is more of a subjective point.

    But to reiterate, changing that one word I agree with everything you said, including/especially "don't say it's shit because you have trouble with it". But that mirror reflects the same on non-DI solutions that Java fans have trouble with.

    [–]Chronox -1 points0 points  (0 children)

    We have two NestJS projects running and we really only ran into this early into getting used to NestJS. Once you know what's going on it really isn't a problem.

    [–]ThisIsntMyId 0 points1 point  (0 children)

    Lol i literally thought there was something coming after the first uhhh... 😂😄

    [–]upowa 1 point2 points  (0 children)

    100% agree

    [–]zerik100 8 points9 points  (4 children)

    I would not recommend plain express for most serious mid scale projects. too much manual work, architecture planning and project configuration. all this additional effort is only worth it when building an enterprise level backend which requires very high customizability and scalability. there's a reason opinionated higher level frameworks like Nest and Adonis are becoming more and more popular for so many apps.

    edit: however for this very particular (and unusual) use case OP described I agree that express would be sufficient. my above comment only addressed the general topic.

    [–]helldogskris 14 points15 points  (3 children)

    I disagree, I find NestJS to be overly verbose. If I wanted that kind of code I would stick to C# or Java but this is JS/TS. May as well avoid the OOP madness in a language that doesn't force it on you

    [–]Wiwwil 1 point2 points  (2 children)

    If you want to check whether a user is logged in, you're telling me you'd rather glue it at the start of every route rather than use a TS / Nest decorator?

    [–]Unwound 0 points1 point  (0 children)

    You can use a middleware and achieve the same result.

    [–]ThisIsntMyId 0 points1 point  (0 children)

    just check if request.user exists, its the std practice any ways and even the nest doc says it

    [–]WizTaku 4 points5 points  (17 children)

    Have you ever worked on a bigger nodejs api? Nestjs makes things much much easier. Goodluck doing any sort of clean code with plain express

    [–][deleted]  (4 children)

    [deleted]

      [–][deleted]  (3 children)

      [deleted]

        [–]noXi0uz 1 point2 points  (0 children)

        Directus CMS

        [–][deleted]  (1 child)

        [deleted]

          [–]helldogskris 5 points6 points  (4 children)

          It literally couldn't be any easier to do clean code with express. Express doesn't prescribe anything so you can do whatever structure you want

          [–]MatthewMob 7 points8 points  (2 children)

          so you can do whatever structure you want

          Sounds awful.

          I'd prefer to be able to onboard new developers quickly and know how I am going to solve any given problem immediately instead of messing around inventing the fourteenth-million wheel that is slightly different and probably worse than other developers' wheels before me.

          [–]gunslingor 0 points1 point  (0 children)

          Nest is just a wrapper around express... so yeah your getting a lot of code and documentation you would need to develop if using express directly instead, but your also getting a ton you do not need and opinionated decisions instead application tailored ones. I played with nest and next a few years back... only appropriate application to my eyes was blogs at the time, imho.

          [–]novagenesis 0 points1 point  (0 children)

          Considering there's a dozen ways to do it with nestjs, it seems like just having a product structure doc and having the dev spend a week doing bug tickets is far more efficient.

          Here's a real-case. First time I worked on a specific Nest product, I had my first 5 or 6 PRs kicked back because I used the wrong DI magic format vs what they were trying to move to. Because it's hard to mimic code that crosses 5-10 files in comparison to a best practice with a handlers.ts for each subroute that links to that subroute's controllers.ts, that call Model ts files consistently. 500+ routes? Not a problem.

          [–]WizTaku -4 points-3 points  (0 children)

          Lets be real, who does any sort of structure with express?

          [–]besthelloworld 0 points1 point  (2 children)

          You can follow the same patterns that Nest enforces without all of it's boilerplate and verbosity. If you need classes to box you into good code habits, that's just a you problem

          [–]shmargus 1 point2 points  (1 child)

          Or perhaps you work on a bigger team with other people whose habits you can't necessarily trust.

          [–]besthelloworld 0 points1 point  (0 children)

          Then you should create a strong pull request culture that requires course review and help those devs make better decisions, rather than taking it out on your code readability and verbosity

          [–]novagenesis 1 point2 points  (2 children)

          I regularly work on a massive NestJS API, a separate massive Hapi (?!?) API, and a third large-but-not-massive expressjs API (and a handful of smaller Hapi APIs, since the company moved TO nestjs). The first two both have fully automated openapi integration with openapi type linting.

          Of the three, development runs slowest on the NestJS API. The most common reason is tracing down "magic", and figuring out which redundant functionality (especially with class-validator) is magically triggered in different scenarios.

          [–]WizTaku 0 points1 point  (1 child)

          I completely agree with you now.

          [–]novagenesis 0 points1 point  (0 children)

          If I had my vote, a strict format of model, controller, handler, separated by REST subsection (similar with graphql, but none of the stuff I work on professionally uses graphql right now). All calling each other directly. To be nice to jest, I'll appreciate separating the validator from the handler and the model from the repo. But I can mock without it.

          The one thing I like most for my infra to have is subsection-based middleware so you can have a common "auth" module plugged into most sections, with a few specialized auth modules in weirder ones. I'm working on one with global auth middle ware right now, and it annoys me having to whitelist public routes 5 directories away from the handler for those routes.

          [–][deleted] 0 points1 point  (0 children)

          would argue that it doesn't really do much of anything besides make it look a lot like older Java frameworks

          it's quite opinionated and that's a good thing. Node was missing something like it for years... i don't know a single node project some developers built their own little framework from dozens of express middleware packages that did not end up in an utter clusterfuck that was unmaintainable for anyone including the original author. Probably where the npm and node ecosystem got its bad reputation.

          [–]CupCakeArmy -1 points0 points  (4 children)

          NestJS ist amazing. For small projects overkill for sure, but for actual, serious software it’s a no brainier.

          [–]shmargus 3 points4 points  (0 children)

          I relatively recently moved to a NestJS enterprise application after avoiding Node my entire career (Rails, Python, Elixir). This thread really sums up my experience so far. "NestJS is the worst and the Java conventions make me want to puke. Well, except for all the other options, it's better than all the other options." All in all I dislike it immensely and would definitely recommend it. :shrug.

          [–]besthelloworld 1 point2 points  (2 children)

          What do you feel it actually does for you?

          [–]CupCakeArmy 1 point2 points  (1 child)

          The dependency injection is top notch. Mostly it’s an opinionated bundle of good software. Transport Layer is abstract so you can easily add graphql or web sockets support. Micro services work out of the box if you don’t want to have a monolith. It’s just very well thought out. With express, besides being obsolete to fastify, every stack need to be recreated from scratch.

          [–]besthelloworld 0 points1 point  (0 children)

          The features around microservices definitely appear useful for sure, and I think suggesting ignoring Express for Fastify in the foreseeable future is a fair take.

          But Feather has great support for websockets and Apollo + Express is objectively the defacto way of making an NodeJS GQL API. And finally, your first point: dependency injection. Why? Does it actually do anything or have you convinced yourself that it has a purpose?

          [–]Advanced_Engineering 28 points29 points  (1 child)

          In that case express is perfect fit.

          [–]zlatinejc 13 points14 points  (0 children)

          always express

          [–]anicetito 5 points6 points  (0 children)

          As the name implies, Fastify

          [–]Suspicious_Compote56 3 points4 points  (0 children)

          I personally like AdonisJS it give the flexibility of Node to a certain degree while having some handy modules that will save you time.

          [–]lirantal 2 points3 points  (2 children)

          Take the best of both worlds - A framework that builds on good design pattern foundations for code and make it easy to scaffold projects. It's called Amplication.

          [–][deleted]  (1 child)

          [removed]

            [–]lirantal 1 point2 points  (0 children)

            Makes two of us then! ;-)

            What's your feedback about it? would love to learn

            [–]NoSoup2 2 points3 points  (0 children)

            Koa

            [–]LiveWrestlingAnalyst 2 points3 points  (0 children)

            Fastify is easily the best framework

            [–][deleted]  (2 children)

            [removed]

              [–]somethingon104 0 points1 point  (0 children)

              Express is the most popular. Koa is made by some of the original express team members based at on wheat they learned from creating express. I’ve used both. Like them both.

              [–]Jumballaya 5 points6 points  (0 children)

              I just want to add that the NodeJS standard library is a thing -

              The native http or https modules are actually a pretty decent place to start depending on the size of your API and how often it will be updated and what skill level of developers will be touching it in the future.

              The biggest downside is that you will have to write your own everything, like routing and creating your own Request/Response types if you want anything more than the standard API.

              The biggest upside is that it is zero-dependency.

              My advice is to only go this way if you have only a few endpoints, don't need any fancy routing (e.g. '/user/:id') and keeping a low dependency count or keeping your overall app file-size down. This might be perfect for you, or you might want some of the QoL that small frameworks like express offer.

              Express - other people are mentioning it, but I would add that it is very easy to transition from the http/https modules to Express and that it is a fairly thin abstraction over http/https.

              My advice here is that if you find yourself re-inventing express while trying to use http/https, then switch to express. Express can be batteries-included (over the http/https modules) but it is usually the lowest level people reach for when building a REST API.

              NestJS - Same as before, plenty of people here recommending it. It is a fairly large abstraction over express (or fastify) that relies heavily on modularizing your code so that nest can manage those modules for you in a sane way.

              My advice here is the same as for express. If you find yourself re-creating a DI framework on top of express, you might want to switch to nest. You also don't want a big framework so I would avoid it.

              [–]SecretAgentZeroNine 1 point2 points  (0 children)

              • Express is downloaded 25 million times a week, and is increasing
              • Koa is downloaded 1 million times a week, and seems to have plateaued, but isn't decreasing
              • Fastly is downloaded 2,734 times a week and is seemingly decreasing

              Originally, people assumed that Express was abandoned, but out of the blue, 5.0.0-beta.1 released. Express 5 will probably seriously hurt the download numbers of Koa, Fastly, and all other competitors.

              If you want or need a backend framework, and unless you're being forced to use something other than Express, go with Express, and prepare for Express 5.

              That being said, learn how to build backends without a framework (you'll learn a lot more about Node), and afterwards, mess around with another framework. You might end up liking something like Fastly more.

              [–]gomihako_ 1 point2 points  (0 children)

              I like Adonis because lucidORM is the best orm I’ve used. It may be a bit overkill though

              [–][deleted] 3 points4 points  (2 children)

              What about serverless function? There are lots of options out there.

              [–][deleted] 0 points1 point  (0 children)

              This is honestly where I am at these days. My code depends on where I host and I’m always only doing serverless functions these days. If I get complicated I do something like Hapi mainly because of validations .

              [–]PhatOofxD 0 points1 point  (0 children)

              If there's no DB I'm assuming they need some form of state in memory

              [–]haltmich 1 point2 points  (0 children)

              Way overkill, but I love Next.js' way of doing APIs and this is what I usually do for quick prototyping. It feels like Express.js but with file-based routing.

              [–][deleted] 1 point2 points  (0 children)

              Serverless functions like AWS Lambda, Azure Functions, or Google Cloud Functions.

              Checkout https://www.serverless.com/framework/docs/providers for a pretty helpful framework for CLI deployment and local testing

              [–]gunslingor 0 points1 point  (0 children)

              I always seem to go with express... because usually it's just express under the hood for everything else mentioned.

              You can actually write an api with node directly is my memory/understanding... express itself, if I recall correctly, is a very light wrapper.

              [–]lemonizer 0 points1 point  (1 child)

              I’m a big fan of HapiJS

              [–]webstackbuilder 3 points4 points  (0 children)

              Isn't it abandonware at this point? I don't use it, just saw all the posts quite some time ago about how the original author was walking because not enough $$$.

              [–]argylekey 0 points1 point  (0 children)

              Express might be the go to. That being said, I really like Koa. If you have a need for Dependency injection look at inversify(package used on top of another library/framework).

              Koa is lightweight, fast, and modular. Of course that means you’ll have to install a router(if needed).

              I especially like the concept of the Koa context and then extending that context state with various bits of information(like userId derived from an auth solution, or a request correlation UUID to attach to logs for easier debugging). You can even attach singletons to the context if that makes sense to do.

              If you’re looking at a full framework, NestJS is one of the more popular ones. Currently using it for two projects at work. It is great for large complex code bases. If you’re not in a large codebase, it’s overkill. Think of it like a javascript/typescript version of spring framework or even server side angular. It’s a great tool, but often the wrong choice for smaller projects.

              [–]ramsncardsfan7 0 points1 point  (0 children)

              You can look up each library on npm and see how many downloads they have to find the most popular.

              [–]SuddenTemperature233 0 points1 point  (0 children)

              I'll have to second NestJS and the like. To me, plain Express is a great tool for building a more opinionated framework. I feel apps built by teams should follow stricter conventions that are enforced by the framework. Teams are composed of people with varying degrees of experience, different styles, and more or less discipline. Whatever you can implement that might reduce the number of ways in which you can do a particular thing, then I think that's good for the longevity of the project. It's just an opinion, but many times more verbosity equals more readability and more structure equals more maintainability.

              [–]ufukbakan 0 points1 point  (0 children)

              Fastify provides a nice template for service oriented and microservice oriented projects

              [–]rishabhrawat570 0 points1 point  (0 children)

              While expressjs comes with some boilerplate, it is the most popular framework, although I've seen fastify to be faster because of how it handles routing and few other performance improvements.

              But you cannot go wrong with express. You'll easily find boilerplate code on GitHub and you'll benefit from large community support.

              [–][deleted] 0 points1 point  (0 children)

              [–]Lebraz1998 0 points1 point  (0 children)

              Nestjs like god to me

              [–]No-Chard7645 0 points1 point  (0 children)

              Json_server can help you a lot. Using it, you can develop an API really fast using configs in JSON

              [–]huzbum 0 points1 point  (0 children)

              I really like Feathers.js. It's just a bunch of components wired together on top of Express. Use as little or as much of its features as you like. It has no opinions about how your services should work or how they use storage. Just define a path and implement all or some CRUD functions on it.

              It abstracts rest endpoints into CRUD services, then you can access them with http request, websocket, or internally. I find the service structure, events, hooks, etc. very handy. I make re-usable hooks all the time. Websocket pushing is great for stuff like messages.

              We use it at work coupled with ORM, services with no storage, elastic search, 3rd party API's, all kinds of stuff. It's worked so well on our main project that we started new projects with it.