
Show HN: Server.js – A modern Express alternative - franciscop
https://serverjs.io/
======
rawnlq
Rather than changing express's syntax, I would much rather have a better
express boilerplate generator with an opinionated stack with good
documentation/justification.

I recently started learning express/node and wasted weeks googling for blog
posts for each dependency to figure out how to configure them. I guess this is
somewhat valuable for end-to-end understanding but not for productivity.

There are a bunch dependencies I am now kind of decided on (not for technical
reasons, but because they are clear popularity contest winners) and figured
out how use:

    
    
        body-parser
        compression
        serve-favicon
        express-session
        csurf
        helmet
        cors
        dotenv
        moment
        selfsigned
        chalk
        debug
    

But still a bunch that I haven't gotten to googling and still need to decide
on what to choose:

    
    
        logging (morgan vs winston)
        validation (express-validator, joi)
        auth (passport jwt, local, social)
        session storage (redis vs keeping it in database?)
        database (mongo/mongoose vs pg/knex/bookshelf/sequelize, graphql)
        storage (s3 vs gcs)
        ajax requests (request vs axios)
        mail (mailgun, sendgrid, mailchimp)
        error handlers
        rate limiting
        geo ip
    

I would be so happy if someone took away my power to choose and just forced me
to use something that will "just work".

~~~
dcosson
Totally a tangent but, don’t use moment.js! It inherits some of the parsing
and other quirks from the awfulness that is the JS Date object, the mutability
almost certainly will lead to being bit by a couple of bugs before you
actually internalize it, and the time zone support is kind of tacked on as an
afterthought.

I highly recommend js-joda, particularly if you’ll ever be computing/showing
things to your users in different time zones. It actually treats dates and
times rigorously, and has an api that makes it clear what kinds of operations
make sense to do on a zoned vs local datetime and makes things like converting
between timezones vs transposing them explicit and simple.

~~~
cabaalis
I've always been of the opinion that timestamps should be stored UTC datetime
or unix timestamp on the server side and then displayed to the proper locale
by the client's device. Is this not a good method?

~~~
mrighele
It is not good enough. All the major browsers that I tried do not properly
handle the timezone offset, as I discovered a few days ago (I put a more
complete answer about this in a stackoverflow answer, but I don't know if
putting the link would count as self-promotion so I will leave it out)

In short, the ES5 specs [1] say that

    
    
        The implementation of ECMAScript should not try to determine whether the 
        exact time was subject to daylight saving time, but just whether daylight 
        saving time would have been in effect if the current daylight saving time 
        algorithm had been used at the time. This avoids complications such as 
        taking into account the years that the locale observed daylight saving time year round.
    

This means that if your country handled daylight saving differently in the
past, converting the timestamp to string may give you a wrong answer (this
would be the case of a number of european countries during WWII).

The spec has been improved starting with ES6 [2], but to my knowledge no
browser has fixed the issue:

    
    
        An implementation dependent algorithm using best available information on 
        time zones to determine the local daylight saving time adjustment 
        DaylightSavingTA(t), measured in milliseconds. An implementation of 
        ECMAScript is expected to make its best effort to determine the local 
        daylight saving time adjustment.
    
        NOTE It is recommended that implementations use the 
        time zone information of the IANA Time Zone Database 
        http://www.iana.org/time-zones/.
    

A solution is to use a JS library that has its own timezone database.

[1] [http://www.ecma-
international.org/ecma-262/5.1/#sec-15.9.1.8](http://www.ecma-
international.org/ecma-262/5.1/#sec-15.9.1.8) [2] [http://www.ecma-
international.org/ecma-262/6.0/#sec-daylight...](http://www.ecma-
international.org/ecma-262/6.0/#sec-daylight-saving-time-adjustment)

~~~
mirekrusin
It's good enough (and correct) to store unix timestamps. For displaying the
date - your comment applies...

Unix timestamp refers unambiguously to single point in time. Interpretation of
this point in time in different timezones is complicated but it's outside of
it.

~~~
mrighele
I agree that storing unix timestamps is a good approach.

My issue was with "then displayed to the proper locale by the client's
device." I mean, by itself it is ok, but in the case of a web client one
cannot unfortunately just use the Date object and convert the timestamp to a
human readable string.

------
franciscop
It _is_ built on top of express to keep all of the good things, but it adds
basic middleware and some more advanced functionality like websockets through
socket.io and security through helmet by default.

It is designed to work perfectly with Promises and async/await, the _new_ ES7
features that makes asynchronous code awesome. Also, I put a lot of work into
making the documentation extensive and clear and I'll keep working on that for
the future while preparing for the 1.1.

Edit, release notes: [https://medium.com/server-for-node-js/server-
js-1-0-released...](https://medium.com/server-for-node-js/server-
js-1-0-released-12a419ab187a)

~~~
josephg
Why socket.io instead of just plain websockets? Socket.io adds a lot of
complexity in the client and the server. What commensurate benefit does it
provide?

[http://caniuse.com/#feat=websockets](http://caniuse.com/#feat=websockets)

~~~
Can_Not
Socket.io adds rooms/namespaces as a feature, automatically reconnects with
effort to not have all clients reconnect at the same time, covers
compatibility edgecases, heartbeat, timeouts, custom events, multiple
transport methods, server side implementations in multiple languages, supports
non-ws fallback for reasons that might not be browser compatibility, and a
good API.

------
TheAceOfHearts
I'd argue koajs was the first modern express alternative, although it's
arguably more of a connect alternative. I've been happily using it since
generators were available under a flag with node 0.11 and it has always been a
joy. There's a huge list of middleware [0] on their wiki, and you just pull in
whatever you need.

It means that your initial setup takes a bit longer, but it forces you to
understand all the moving parts.

The session in production tutorial makes no mention of secret rotation, which
I'd consider an important detail for a production environment. The docs don't
mention the feature either, but if you look at the underlying express-session
library you see that the secret can either be a string or an array of strings.

Although redis is an amazing tool, I disagree with recommending it as the
first choice for a session store. Unless you really need it or plan on using
it for more stuff, you'd probably be better off keeping sessions in whatever
data store you're using for the rest of the application. That lets you avoid
having to setup and maintain yet another tool.

No documentation at all for how the socket.io stuff is supposed to be
configured. Chat tutorial assumes a single-node environment, which I'd
consider unreasonable for anything outside of a hackathon. Wouldn't you at the
very least want a process per core?

[0] [https://github.com/koajs/koa/wiki](https://github.com/koajs/koa/wiki)

~~~
franciscop
I didn't know about that middleware list, thanks for sharing.

About session rotation, it was my impression that it is a smaller problem
compared to how it can be exploited if we're using cookies [1][2], could you
share some more info about it please?

About Redis, I totally agree. You can add any store that you want with the
plain `{ session: { store: ... } }` option. There is an issue though for some
of them that need the original `session` passed in which I'll have to fix. So
the main fix would really to improve the documentation to explain how to use
the appropriate store.

Finally about socket.io, I also agree. I am not a large-scale system expert,
so this is part of my limitations and that's why I recommend server.js for
small-to-medium sized projects. Long-term I am working on improving on my
knowledge here, but not the highest priority right now (compared to security
for instance). Also, socket.io right now is not stable officially, so use with
care. I'd love any help in here if you want to share some of your expertise.

[1] [https://stackoverflow.com/questions/2846401/does-session-
id-...](https://stackoverflow.com/questions/2846401/does-session-id-rotation-
enhance-security)

[2]
[https://www.owasp.org/index.php/Session_fixation](https://www.owasp.org/index.php/Session_fixation)

~~~
franciscop
Note: socket.io is stable; I mean the internal glue for using socket.io with
server.js

------
drinchev
> Note: this option can be ignored and server.js will work with both .pug and
> .hbs (Handlebars) file types.

[1] :
[https://github.com/franciscop/server/blob/master/package.jso...](https://github.com/franciscop/server/blob/master/package.json)

I think around express 3 the guys decided to go with a modular approach and
decouple the server from any of those heavy ( render ) libraries, as well as
body-parser ( once it was core module in express itself ).

My really friendly feedback is that I think express carries so much experience
that it will be really hard to replace it with something so monolithic. I use
express for REST APIs as well as full web app, where I need no render engine
and having this installed on my server is an overkill.

Best approach I would think of is having someone rewrite express from scratch
and call it express 5, while keeping the same balance of core and extra
functionality, as well as new async / promise goodies.

~~~
kosinus
Basically what I find Koa does for me: [http://koajs.com](http://koajs.com)

~~~
vidar
I am in the Koa boat as well, does Express have anything that Koa does not?
(not trying to start a framework flamewar, honestly!)

~~~
franciscop
IMHO, and one of the reasons I decided to go with server, _simplicity_ is a
feature and the advantage of express over Koa. It is hard enough for new users
to get started on Node.js, but to have to handle all of the new middleware
concepts, PLUS to have to learn a lot more advanced features like generators
is a no-go for my framework of choice.

\- server: return something to reply to the browser. Can use `async` for more
advanced features.

\- express: reply.send() is fairly straightforward. next() for middleware is a
new concept but conceptually in the right place (when you are digging a bit
deeper in the middleware).

\- Koa: yield, function with asterisk, etc.

So I think Koa is fine for devs who have been a while in JS dev, but the
learning curve is too steep to get started. Same as what happens with React
and the reason create-react-app has become so popular.

~~~
kosinus
Koa has been doing async for a while. It's basically connect with promises
instead of callbacks: `app.use(async (ctx, next) => { await next(); });`

~~~
mikermcneil
As long as you're on Node >=v7.9, you can also use `await` in Sails, Koa, or
any other tool that supports promises. There's some work we had to do to make
it feel nicer, and we had to update docs and stuff, but for the most part it
was pretty painless-- all thanks to the JavaScript engine.

And `await` is so much easier and safer than callbacks in userland code!
Really excited about Node.js in 2018, now that `await` is supported in the LTS
release. Callback hell is finally dead.

(Diff showing a refactor of an example app from traditional callbacks to
async/await:
[https://github.com/mikermcneil/chatkin/pull/4/files](https://github.com/mikermcneil/chatkin/pull/4/files))

------
benologist
This is OK but a hello world app requires 203 modules and that's not really a
safe position to start new apps.

[https://github.com/ChALkeR/notes/blob/master/Do-not-
underest...](https://github.com/ChALkeR/notes/blob/master/Do-not-
underestimate-credentials-leaks.md)

------
amk_
Fastify is a similar project that aims to be faster than Express and adds a
number of API improvements like baked-in schema validation for routes,
logging, and async-by-default APIs.

Haven't used it in production but replaced Express with it in some side
projects.

Since server.js is built _on top of_ express it might even be possible to
build a variant of it on Fastify instead and get those benefits as well.

[https://www.fastify.io/](https://www.fastify.io/)

------
weego
So it's just another express abstraction rather than an alternative then,
considering express is a dependency.

------
chmln
This might be somewhat negative, but I don't quite see what problem the
library is solving.

It looks like as if Express wanted to become more like Koa (obvious from the
context object). Frankly, it has missed out - koa's simplicity and elegance is
unmatched. The routing and middleware syntax is particularly clunky.

Documentation seems really nice though.

~~~
franciscop
No problem, didn't sound negative. The main difference with Koa would be
having a starting point with default middleware, security and websockets. I do
agree with your points, Koa is probably the most elegant library out there,
probably followed closely only by express.

But that is not why I created server. It is not about library elegance and
simplicity, it's all about making it easy to use. Both of Express and Koa
involve external middleware that the user has to manage manually, and there is
a subset that is really common for most situations. Server.js is all about
usage simplicity, including this subset by default and making things work by
default.

Context was inspired initially by the way Promises work with a single return
value, but then expanded further (and named after) Koa's context.

~~~
simplify
Isn't koa flexible enough for you to build a framework on top of it to
accomplish your goals of elegance and simplicity? That way you could take
advantage of the ecosystem that already exists, instead of trying to bootstrap
your own.

------
maxpert
Title should say wrapper rather than alternative. Since it’s built on top of
express.

------
mynegation
Coming from Python, my understanding is that Express is sort of like flask
(add your own everything), and something like sails.js is like Django
(bundled, convention over configuration). I am wondering, why, unlike, Python
and Rails, Django-type frameworks did not take off in Node.js? I would like to
have a popular “Django.js”, so I am rooting for this project.

~~~
franciscop
My opinion is that Node.js follows a lot more the philosophy of small reusable
modules, which is a lot more flexible with the disadvantage of a lot more
initial work. I still don't think server.js is Django.js-like, since it leaves
most decisions up to the developers. The main difference is that Django,
Rails, Sails, etc are opinionated about both the libraries AND the code
structure, while I tried to keep server opinionated only about some basic
functionality, but leaving the more advanced and code structure totally up to
the devs using it.

But I do try to do batteries-included, because express-like workflow involves
following a bunch of steps that are basically the same for most projects.

Edit, maybe you are interested on Sails:
[https://sailsjs.com/](https://sailsjs.com/)

------
sideproject
As a side thing... is anyone getting a little wee tired of reading the
following magical statement about every framework that comes out? :)

> [insert the latest framework here] that just works so you can focus on your
> awesome project

~~~
franciscop
Ah I didn't even think about it being a thing, thanks for the feedback. I did
make server so I wouldn't have to worry about so many middleware pieces any
longer and could work on my actual projects, but I see how this is fairly
common wording.

------
kevinSuttle
If you’re just looking for a barebones static file server try this:
[https://github.com/zeit/serve](https://github.com/zeit/serve)

------
mtarnovan
Imagine googling for stuff about this project... (issues, bugs, tutorials etc)
Must be a nightmare, with such a generic name

------
slackingoff2017
Express is ripe to be replaced. It has the weirdest syntax I've ever seen and
is basically designed around call back hell.

I can't wait till somebody rebuilds it in Typescript or at least around async

~~~
always_good
[http://koajs.com/](http://koajs.com/)

In Koa, handlers don't respond to the request. Instead, they update a
representation of the response and return a promise. The response bubbles up
to the top-level where the `res.send()` is done.

This way you have real middleware. You can post-process the response or do
something else entirely after the downstream has run.

    
    
        const middleware = async (ctx, next) => {
          console.log('request going down')
          await next()
          console.log('request coming up')
        }

~~~
slackingoff2017
Haha this is exactly how I pictured it working! Made by the makers of express
too.

------
debacle
It's very interesting watching node developers re-implement the PHP ecosystem.

~~~
DTrejo
it's very interesting watching php composer developers reimplement the npm
ecosystem ;)

~~~
bagol
It's very interesting watching both of your comments XD

------
jroseattle
Are there docs or maybe a blog post that identifies the value-add on top of
Express? While I see the API design example (which applies to me), we already
do that with Express v4 (it's more code organization than anything else.)

I'm super-interested, but I'd like to know at a deeper level what this gets us
over plain Express.

------
ekryski
I think a lot of people still haven't seen
[https://feathersjs.com/](https://feathersjs.com/). Has been around for a
while and offers all of this and more AND is drop in replacement for Express.

------
zmix
Is there any Node.js web-framework/app-server like Express, that uses XML as
backend, rather than JSON? Or, that can have this plugged in, at least? I'd
like to use BaseX (XML document database) as a backend to something like
Express.

------
segphault
This pulls in over 200 dependencies, with a total weight of 37MB. I'll pass.

~~~
franciscop
Only 37MB? I expected more TBH, I guess I am too used to the dev side of it.
37MB is really cheap compared to the hours that you save by not doing
everything manually, even more when you consider the quality of the underlying
libraries from a security point of view.

Long-term I would like to reduce this and have some ideas in mind, but right
now this is not an issue.

------
nawitus
Does it support automatic documentation generation for the API (kinda like
what swagger + express.js does)? That's the biggest missing feature in
Express.js for me.

------
arrty88
Does passport plug into this?

~~~
nawitus
Passport can be quite easily used with any framework, but of course an
existing library can make it even easier. Though to be honest Passport.js is
trivial enough that I don't see a need for it usually..

------
jypepin
Surprised at their choice of socketio instead of leveraging http2 streams.

------
itronitron
no mention of TLS, which is unfortunate

~~~
clintonb
Why? TLS/SSL termination is normally (at least on every project I've worked
with) handled by the web server.

~~~
franciscop
Exactly, it was initially intended to be a core feature but after searching
around (and from my experiences) I found out it is rarely done at the
language-level.

------
myf01d
> npm install server

How could the package name "server" be available all these years :D?

~~~
XCSme
Asking the real questions! I wonder if deleted package names are made
available again. It makes sense that they did, but it's also a security issue,
if one package is removed an attacker could add a new package with the same
name and with a malicious functionality.

~~~
alvis
In theory, no. Unless you have the magic power like what Laurie Voss have.
Remember he saved the world by resurrecting left-pad[1]?

[1] [http://blog.npmjs.org/post/141577284765/kik-left-pad-and-
npm](http://blog.npmjs.org/post/141577284765/kik-left-pad-and-npm)

