There are lots of tutorials written to teach people how to use popular Node modules to handle routes and creating http servers, like Express or Koa. We all get too spoiled by the easiness of Node packages that we forget how easy to use Node core functions are. It’s tempting to import a library for every functionality we want to implement, but we should step back and think if that’s really what we need.
One of the main use cases for using only native modules is tests. Each test case is written for one scenario only. The code does not need to be extensible, because it’s not exported to anywhere else. The DRY (don’t repeat yourself) rule don’t apply to tests. You want to repeatedly test every scenario using slightly different case.
Packages like Express can handle a lot of cases for you, like taking in different types of routes, makes it easy to handle errors and then some. This makes the development process much faster but for tests these benefits irrelevant. A lot of things can happen because it depends on so many modules. I’ve run into many cases when there is a vulnerability found in a package that’s a submodule of a submodule of a submodule of a very reputable and well-maintained module, and our CICD process fails for a couple of days before we can put a patch in the module in question. The last thing a developer wants to fix in a failing test is the test itself.
In my experience, Node core is much more stable than any other node modules. It’s a very rare scenario that Node itself would break something and a library picks up the slack, which has been my experience following contributors of Node core and when they hear the needs of users and module developers regardless if they’re independent devs or large companies.
There’s also nothing worse than jumping into a big Node.js codebase where there are packages that’s 3.2M and only ~30 lines of code is used. Although, another bad practice is to write your own implementation for functionalities that have been well established by commonly used modules, and leave it poorly documented or tested. It’s a balance, and you as an engineer have to decide what to do based on your scenario.
tl;dr
- Use only native node modules in tests
- Node core is much more stable
- Reduce node_module size
Without further ado, here’s a snippet I always use to serve up pages quickly.
1. Setup
You only need to have a stable version of Node installed, there’s no package dependency, so don’t even need package.json
or do npm install
.
2. index.js
I’d recommend you open the http
documentation in conjunction of looking at the following code snippet.
The http.Server
class in Node is pretty straightforward. The http.createServer
method returns a http.Server
class object, which we will save to a variable called server
and use it later to call server.listen
method to open the http server port.
The http.createServer
method takes in an options
argument(post v9.6.0) and a request
listener, which you can pass in a (req, res) => {...}
function to tell the server how to handle request and response. The first argument is always the request
object, and the second argument is always the response
object. Each of these objects has different properties and methods. The request
object has properties like res.url
which tell you the path of which people are visiting the server. The response
object can just send a pack of data with res.end
, or persist a socket connection; you can specify a file to send over, etc.
Note that, unless you’re persisting a socket connection, or sending chunks of data, the res.end()
method should be used because the response connection needs to end after sending the data.
const http = require('http');
const path = require('path');
const testPage = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h1>browser test</h1>
<script>console.log('you can serve up scripts with this')</script>
</body>
</html>
`;
const server = http.createServer((req, res) => {
if (req.url === path.normalize('/')) {
res.end('This connection is alive!');
} else if (req.url === path.normalize('/test')) {
res.end(testPage);
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end("this page doesn't exist");
}
});
server.listen(3000);
3. Run
node index.js
Go to localhost:3000, localhost:3000/test to try it out.
Hi Shiya, great article. Makes me think twice about using express for API development. Thanks.
Test comment
Hi,
I like your site.
Can you share how did you make the site?
What technologies/framework did you use to build it?
Thank you.
It’s a WordPress site, deployed to AWS EC2.