Express is currently, and for many years, the de-facto library in the Node.js ecosystem. When you are looking for any tutorial to learn Node, Express is presented and taught to people.
In the latest State of JS survey, Express was TOP 1 for all categories.
Despite all of this, Express is not a great technology, and you should have stopped using it since 2015.
--
It is unmaintained
Express has not been updated for years, and its next version has been in alpha for 6 years.
People may think it is not updated because the API is stable and does not need change. The reality is: Express does not know how to handle async/await
.
Matteo Collina@matteocollina
Yet another Nodejs project recommends using async/await in Express middlewares.
I only see memory leaks everywhere. Hopefully from @nodejs v15 we crash on unhandledRejection.. at least they’ll all see their problems before reaching production. 🤞🏼20:53 PM - 13 Jan 2021
If you are using async/await
code inside your route's handler or middleware, you are prone to UnhandledPromiseRejectionWarning
exception. Express will not handle those exceptions for you because it does not know them.
There are multiple issues (#4360, #4348, ...) in Express' repository about people having this problem.
You should know that from Node 15, your application will crash when encountering this exception, and before this version, you will have a memory leak.
When using async/await
, you should always ensure that the library accepts an AsyncFunction
as a callback. Here is a great talk named Broken Promises about that.
--
It is a low-scope framework
The word "framework" is a wild term. When you are looking closer, Express is a routing library that supports middleware, but it is still called "a framework".
Evan You had a great talk about seeking the balance in a framework design. He said that we should categorize a framework by its scope.
We can categorize Express as a low-scope framework.
When you are building an application, you need more features than a routing system.
You need to:
- access a database;
- validate your data;
- create an authentication layer;
- create an authorization system;
- etc.
All of those features are not inside Express and should be glued by yourself.
I've always been amazed to see people fighting so hard to make something work by glueing modules instead of choosing a real solution to their problem. 😐
Stop creating your undocumented homemade-framework on top of routers and start working on what matter. twitter.com/_bitkidd/statu…07:37 AM - 10 Sep 2020Kirill @_bitkiddWrote a short story of my way to @adonisframework and why I chose it for every day work https://t.co/e6bCrXhqeK
Gluing those modules yourself means taking all the risk to add memory leaks, security holes, and bugs to your application. On top of that, you are only losing time and money because you should not be the one responsible for doing that.
--
Alternatives
What are the alternatives? What should we teach to people?
Even if I believe low-scope framework should not be used, there are few people that like this style or need one for learning purposes. In this category, you should look at fastify.
This framework is well maintained, and provides an official compatibility layer for Express to help you migrate your application.
If you prefer to have a high-scope fully-featured framework that lets you focus on your business logic, you can use AdonisJS.
There is no reason to stay with Express, only future pain that you can avoid today.
--
Do I hate Express?
The goal of this section is to add a disclaimer to this article. I am not hating Express. I am sharing my perspective to help others make informed decisions and not follow the herd.
Express was one of the first frameworks in the Node.js ecosystem, and it was great for many years! But now, it is time to let it go.
I want to push the Node.js Ecosystem further and help newcomers to learn a technology that will not explode in their hands.
Discussion (66)
Seriously, give AdonisJS a chance. It's a real joy to work with, especially since v5.
damn it looks cool
Coming from Rails and needing Typescript support and intellisense, Adonis v5 seems absolutely perfect!
A little bit of shameless self-promotion:
I made a plugin for Adonis that integrates it with another great technology - inertia.js
I'm not sure access to a database should have anything to do with the web framework
yerp. I'm sure some people are kind of stuck having to do that for some reason, but for the most part db + web framework is a net negative that should be avoided.
Interested in why you think this way, could you explain further?
In my experience, it allows for seamless integration with other parts of the framework, so you don't have to write the glue code for it.
Also, frameworks come with support for multiple DB drivers that make switching the engine straight forward.
It depends where the framework puts this glue code. If it's straight in the controllers for example that's not always a good idea. Maybe it can work in simple CRUD app, but for anything more complex you want your persistence logic somewhere else (far from domain business logic)
Yes that’s true, but my point is about monolithic server-side web frameworks vs. a more service-oriented architecture. The latter enables any client (web apps, native apps, cli) to use the same service and also avoids throwing all traffic at the same server.
I'm sure access to a database should never have anything to with the web framework. :)
Strongly disagree. Despite the good intention of the author, this article may lead people to make bad decisions. Here's why
async/await
), stick to the code that has been vetted by many people in the past. The js community is really excited about the modern js(so am I) but jumping on it without looking at the support for the essential tools is a mistake.I have to agree with you on these points.
I do agree that the async/await should be fixed, but...
React is somehow also a low-scope framewor, does it mean it's bad compared to Angular?
What do you think about tools using the unix philosophy? Doing one thing well?
In my opinion, when you are an experienced developer in a given ecosystem, you prefer to assemble low-scope tools yourself instead of relying on opinionated choices of a high scope framework.
Last production release of Express was about 2 years ago, not 6.
github.com/expressjs/express/relea...
Just because they haven't released a major version in a while doesn't mean it's unmaintained. There's still plenty of active development going on.
Whenever a getting started says to use Express, my default has been to use Koa, which works ok and had mostly been my default since it was billed as "the Express founders decided to make express but with better async and fewer leaks." This thread is full of great alternatives, though - looking forward to checking them out.
I was thinking the same, also Hapi is missing here, it has been around for some time like express and koa.
I personally love the single argument
ctx
style of thinking - especially since the request-level context is often passed to other functions!I feel offended by the title. ExpressJS is still perfectly valid to use, it's very stable and given its ecosystem there exist many plugins for authentication/security/etc. But I understand what you want.
I tend to select different frameworks every time I start a new project, so that I can reduce the risk when a framework starts to break down.
It's my first time knowing the technical shortcoming of Express.
I have one Express app full of await s. Looks like I'll have to redo that app.
Is express becoming the jQuery of the backend?
I wouldn't say the issue is
async/await
exactly or that it's new. It's never really handled Promises well.Most common "solution" is to create a little
asyncify
function.(quick off the top of my head, didn't debug this)
and then use it around functions in your express app
It's mildly annoying but the automatic handling of async functions isn't a deal breaker for me. You'd also be surprised how often you don't need an auth layer or a database built in for small projects.
There is quite a bit missing express, but that's what I like about it. It's flexible and easy to hack on top of. It's not the right tool for every project and probably not the best choice if you want something with batteries included. Like any project, you check your requirements and then choose what tools you use. I'll probably keep using express for a while just because of how flexible it is.
Also, the source code is a nice read if you every need to really dive into debugging.
(Unpopular opinion, I'll just use rails or django if I want something stable, with a database, with built testing and batteries included)
aex gives a totally new way on how web framework should be with node.js.
It is lightweight, fast, simple.
And it answers your concerns in a simpler way than almost all framework currently exist.
There is no (big) improvement from express to fastify, and the design principal may be even worse than express.
If you should drop express, you should first drop fastify.
I have been using async/await for years with express, there is nothing wrong with it.
low-scope is very good and important for a pure web framework.
express doesn't have any big problem.
but needs more decorators and cleaner, faster code.
Aex provides scope to embrace new things through middlewares, but still low scoped on its own.
most well-designed, low-coupled middlewares for express can be reused in aex.
a simple aex handler.
see more details here
aex looks like nest.js have you ever used that?
Recently started using nestjs for a new project, really good to use and adds structure to code, however it does still use express or fastify
If they looks like, then all node.js frameworks look like each other:)
they only looks like in using decorators.
Haven’t heard “low-scope” yet, so thanks for that. I prefer low-scope frameworks. I like the ease-of-use, low barrier to entry, flexibility, freedom to use complimentary libraries. And the relatively low commitment that makes abandoning them possible really wins me over. I’ll be taking a look at fastify
Loved it, mainly because of validation with ajv and fast json stringify.
And, simple yet perfect validation is a deal breaker for me.
Also, integrates well with OpenAPI.
If you like working with TypeScript, with Dependency Injection, with good modularity, and you don't mind trying the beta version of the new framework, you can try Ditsmod.
Yes, it's like Nest.js, but it is simpler, has built-in support for nested routes, has a clearer scopes of providers (per application, per module, per request), and has no Express under the hood.
If you are cloning repository, then you can run the examples as follows:
Hi from Dou)) ✌️
Express is aiming to be minimal and there are frameworks with more features built on top of it. If it wasn't minimal and would contain ORM etc. it would be for the worse as the said frameworks would have to deal with it.
This way you don't have one monolith framework, but something that you can configure how you want/need.
For those who are looking for alternatives
I am the author of tinyhttp, Express-like framework but rewritten from scratch and without useless v0.10 polyfills and with
async
/await
support. And yeah it targets latest (>12.4) Node.js versions for minimal overhead.There's also Polka that tinyhttp was inspired from. Although it doesn't come with all
req
/res
methods ootb so depending on your goals either pick Polka or tinyhttp if you need the same API as Express.I agree with the thoughts in your post and especially your disclaimer. Everything has tradeoffs. I think Express is a good starting point for new comers to understand what they can do with a basic framework. One can then take it from there.
I like Fastify's benchmarks section where it compares features and speed:
github.com/fastify/fastify#benchmarks
Is this true if you
try-catch
your Async expressions?It is said the next generation of express (express 5) will play nicely with
async/await
(I've waited for the next generation for years, though). BTW, I'd like to translate this post to Chinese, and publish the translation at nextfe.com. Can you give me the permission to do so? Thanks in advance.If you point to the official article, I see no reason not to translate it to whatever language you want.
I like the services approach moleculer.services, never looked back since jumping on that.
I support this opinion, thanks for the article. I don't consider Express as stable and mature anymore. For me it's a legacy, it doesn't evolve and it's time to stop using it. I recommend Hapi :) serves me well for years
Awesome article. piecing things together have been one of the pains for me in Express. Before I found Sails it gave me the creeps.
I will encourage Node.js developers to also try out a fully featured high scope framework like Sails.
I wrote a getting started piece on LogRocket
blog.logrocket.com/building-a-node...
I think it depends on the size or project you are building and your experience level.
When I first started writing NodeJS web servers I started with a framework for all the reasons the author describes. But I found that the framework was always getting in the way. There was so much code, I found it very difficult to figure out how to integrate various standard middleware, I was learning the framework concepts rather than the more basic concepts.
That particular framework was built on top of express anyway, do one day when I’d had enough if hitting my head against a metaphorical brick wall, I re-wrote the app using just express.
It was one of the most liberating things I ever did on my programming journey.
Suddenly I was able to learn how to build web apps unhindered by the framework.
Of course you have to build things yourself, but there are modules available for most things. I have become a better programmer because of it. Upgrades are easier, replacing a specific part of an app is easier.
Having said that, I can see how if you are building a very big app, having a framework could be very beneficial. I would be happy to use one now, because I have the skills and experience to be able to work with a framework.
An analogy that might be appropriate: a big framework is like an entire building site for constructing a huge sky scrapper. That’s a lot of complexity, but you might need it to build a sky scrapper quickly and on budget. ExpressJS is useful for situations where you are building a shed or a small house, but you might also find a use for it building a sky scrapper, but you’ll have to assemble a lot of things yourself, so might not be appropriate in all situations.
Thanks for share your point of view. About use async/await on express, I using express-async-errors on top of bootstrap app. Something like this: github.com/leandroandrade/node-ess...
This library allow to handle async errors.
Until now I'm not catch a bug report on my apps.
For me express is a good framework. It has and is still serving it's purpose. If you want to have a high scope featured framework still with express, then you have Expresswebjs. You can check it out at expresswebjs.com/
Amazing article, I never liked Express due to its low scope philosophy but I didn't know how dangerous async/await was in Express!
It always is, until you are aware.
Thanks for sharing your thoughts.
While I agree that Express.js might not give back many features, like Django or Adonis, but I'd like to rather presume this as a feature of Express.js itself.
It lets you wire your own application and system in the way you really like it to be. And gluing modules doesn't seem really bad to me. It helps you find the best solutions to your needs. And there are many boilerplates available that can quicken the process.
Of course, there's still the problem with async/await. But I'm not sure why everyone is trying to use async/await all the time. Although this is a great feature of the JS ecosystem, I like to believe that a clean code will rely on clean functions and modularity and will use async behavior only when it is needed. In such cases handling the rejection exception, won't be a real pain.
Yet personally, I'd like to see more progress with the framework. I believe there are ways in which Express.js could improve and get better. I've written codes with other frameworks like Django and Flask too. And I believe all these frameworks can be useful in their own ways.
It mainly depends on what suits the programmer. Some like to shape their own systems and others like to make more awesome things faster.
If you like TypeScript (as I do) try nestjs.com . I like the concept of structuring folders in right way and an idea to separate code into modules. Really elegant way to write good code.
Although Nest.js is better structured than Express.js, the lack of built-in prefix support for nested routes is frustrating. Yes, I know that there are third-party modules that implement this feature, but it's still strange that the author of Nest.js didn't do it out of the box.
Structuring like
user (directory)
-- group (directory inside user directory)
Doesn't work? Shouldn't that create nested routes? Like /user/group
I'm talking about nested routes, like
/api/posts/123/comments/456
Thanks, never heard of this
You can use fastify with NestJS btw
github.com/barelyhuman/seed-fullstack
I'm just using next.js for everything at this point.
If i do want to separate backend from frontend then I have github.com/barelyhuman/ftrouter which I rarely use anymore but then it's not maintained any more because I was the sole user