
Node.js Fundamentals: Web Server Without Dependencies - bloomca
https://blog.bloomca.me/2018/12/22/writing-a-web-server-node.html
======
jpalomaki
IMHO articles like this played a major role in Node's initial success. After
years of working with ever-growing frameworks with huge learning curves, it
was so refreshing to get your first thing running in few seconds. Felt like
basic in the 1980s or PHP in the late 1990s.

~~~
hardwaresofton
IIRC before nodejs+express the req/resp/next paradigm and middleware paradigm
had never been so accessible. Other frameworks had it of course, but it was
often hidden behind layers of abstraction or little quibbly bits. Express gave
you just what you needed for both middleware _and_ handlers:

    
    
        app.get('/', function(req, res, next) {
          res.send('hello world');
        })
    

For comparison, flask:

    
    
        @app.route("/", method='GET')
        def hello():
            return "Hello World!"
    

It's really close, but I find the NodeJS approach even simpler and easier to
understand. Need to access the request? use `req`. Need to access the response
to set headers or something? use `res`. Is your function actually a
middleware? use `next`. It doesn't get much simpler, assuming you understand
node's semantics well (as in "return"ing a value doesn't mean it gets sent).

Django/Rails required whole project scaffolds and usually a separate routes
and handlers files and knowing a whole bunch of stuff. I'm not even going to
get into what frameworks like Spring/Struts required.

NodeJS made it _dead simple_ to get a HTTP server up and running in something
like <10 lines of code.

People shit on JS and NodeJS every chance they get, but innovations like the
amazing standard library (and express), along with npm's ease of use really
pushed the field forward IMO. While I'm praising node I might as well say that
node got decent bolt-on (gradual) type system support way faster than the
other popular dynamic languages as well, but they got there through
transpiling which also looked (is?) ridiculous the first time it became well-
known. I find Typescript much more approachable than typed python[0]. Is typed
ruby even a thing[1]? I don't keep up with ruby so I'm not sure.

[0]:
[https://docs.python.org/3/library/typing.html](https://docs.python.org/3/library/typing.html)

[1]: [https://bugs.ruby-lang.org/issues/9999](https://bugs.ruby-
lang.org/issues/9999)

~~~
devxpy
>Need to access the request? use `req`

Well, I don't see what's especially difficult about this?

    
    
        from flask import request
    
        @app.route('/login', methods=['GET', 'POST'])
        def login():
            if request.method == 'POST':
                return do_the_login()
            else:
                return show_the_login_form()
    

I would actually argue that this is better, since I have to type "request"
only once.

Although I have to admitt, the middleware thing looks quite composable.

~~~
Y7ZCQtNo39
I'm not a huge fan of decorators since they obfuscate the state of the
runtime. What exactly does the call stack look like when login gets invoked?
What variables are in scope? I find it difficult to reason about.

I understand that this function will execute when the HTTP server receives a
GET or POST request at `/login`. The semantics of the decorator is clear-- I
don't particularly take issue with that.

But the second my assumptions about the decorator break down (e.g., I think
I've defined a decorator properly, but I have not), all bets are off on how to
make it function properly. It's not as simple as going to the source code for
the module and see what API's I'm calling.

~~~
devxpy
Well, You'll be happy to know that a decorator is literally just a function
that takes another function as its first argument.

    
    
        @app.route(...)
        def login():
            ...
    
    
    

Is literally the same thing as -

    
    
        def login():
            ...
    
        login = app.route(login, ...)
    
    

Hopefully that clears up the air a bit?

~~~
Y7ZCQtNo39
It clears it up but personally, I'd rather just write `app.route(login, ...)`.
Isn't a lot clearer to use more conventional language features? What exactly
is this buying me?

I don't know if me saying 'Just, why?' is a good enough reason to throw my
arms up and say it's an idea I'm not a fan of. I'm willing to say that it's a
rather subjective attitude.

I guess my retort is that, it's far more confusing to have that syntax, then
explain what it meant, when I could've just used the conventional syntax.

It's not like it's offering me something substantially simpler. For example,
the spread operator that was introduced. It actually allows you to write
clearer JavaScript code. This syntax isn't intuitively clear like the rest
operator is.

------
mirekrusin
Not 100% related to the article but koa with its maybe 300 LoC is hardly a
dependency. However in general nodejs projects definitely suffer from
dependency bloat. I encourage anybody to try for themselves to go through
node_modules in their own projects, it’s quite englightning to see the scale
of the unnecessary, duplicated, reimplementated in different ways crap there.
Conscious aim at shallow, minimal or no dependency in packages and end apps is
definitely something good; less than 5s installs, code audits, more healthy
projects in general. I’m not saying it’s always possible or better to trim the
code fat, but if you’re aware of dependency tree single root dep introduces
you’re usually able to cut it down a lot.

~~~
asien
Koa is appreciated to it's true value by the community.

Express was the most popular at the start and after StrongLoop got acquired by
IBM it made sense for everyone that express was the foundation of Node.JS.

It's sad knowing how much bloated express is and every single Node.js library
uses it from Next to GraphQL server etc...

------
Vanit
I still write little http servlets like this sometimes, especially for
something like gluing IoT services together.

------
lioeters
Great article. Anyone working with Node.js should be familiar with these
fundamentals. It also demonstrates the simplicity (and dare I say "elegance",
though that's subjective..) of Node.js and its concepts.

These days my favorite library for writing an HTTP server is micro [0] (and a
few middlewares). I like how it provides a minimal, functional layer of
abstraction.

[0] [https://github.com/zeit/micro](https://github.com/zeit/micro)

------
brod
There are _a lot_ of gotcha's when rolling your own web server based on the
http and https packages and I think the conclusion of the article could have
gone further in addressing what they are and in what context they might
matter. I recently wrote a little zero-dependency NodeJs http/s server[1] with
an equally dumb router for some dev tools which could benefit from a simple,
promise based api, for most other use cases I'd just pull in express or
something more mature.

[1][https://github.com/8eecf0d2/decade](https://github.com/8eecf0d2/decade)

------
gyrgtyn
Love this. There was this project along the same lines, from the olden days of
node:

[https://github.com/Raynos/http-framework](https://github.com/Raynos/http-
framework)

------
tofflos
It's nice to get away from frameworks from time to time. If anyone is
interested in something similar written in Java I recently created a couple of
examples based on Undertow. They are available at
[https://github.com/tofflos/undertow-
examples](https://github.com/tofflos/undertow-examples).

------
craftoman
Performance is also a major advantage. Express is extremely slow compared to a
basic "native" API without dependencies. If you check out the results in
numbers, you'll be amazed.

~~~
tozeur
Please post some citations to back up your performance claims. I haven’t found
strong numbers online.

~~~
asien
> Please post some citations to back up your performance claims.

According to TechEmpower benchmark[0],Node.js-MySQL is two time faster than
express-mysql.

Others benchmarks of TechEmpower tend to point exactly the same result in
terms of performance for express.

[0]
[https://www.techempower.com/benchmarks/#section=data-r17&hw=...](https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query)

------
partycoder
The crimes of these kinds tutorials:

\- Downplaying the role of error handling

\- Treating the subjects they cover as a black box

\- Not warning that the code examples are not suitable for production

------
nurettin
you can do the same (except loading certs) with python3 these days thanks to
asyncio.

------
keketi
But can it left pad a string?

~~~
GordonS
JavaScript has come a long way in recent years, but the lack of a
comprehensive standard library is still absolutely mind boggling.

~~~
emilfihlman
This is really pretty sad. A standard library is paramount to a stable and
easy to develop ecosystem.

~~~
hombre_fatal
It may be, but this is a weird thread to bring that up since Javascript has
padStart, and TFA is about building a web server with only the standard
library.

~~~
nurettin
the OP was referring to this incident [https://github.com/stevemao/left-
pad/issues/4](https://github.com/stevemao/left-pad/issues/4)

where a very basic package everyone depended on was yanked from npmjs.

azer's original post:
[https://news.ycombinator.com/item?id=11340510](https://news.ycombinator.com/item?id=11340510)

