Let’s Build a Node Framework
This article is one of the few articles that I am going to write and explaining the various aspects of using Node JS without any framework like Express, Sails, etc.
The motivation for this came from the fact that NODE_MODULES on some of these things can be really nasty plus there are tones of things to be leaned during the process to trying to Build something like this. So, let’s jump in.
I wanna confess something:-
Remember when I said we are going to build a framework, I kinda lied a little bit. See a complete framework is a combination of an immense amount of work and collection of tools. So, to build something like that on my own is kinda extremely hard. So, instead of build a framework, we are going to build parts of a framework such as Routing, etc.
Some key things I wanna mention upfront, so that readers can have a clear idea of what they are getting themselves into.
- This is going to include a lot of Reading and Writing Files, Serialization, Conversion of form, etc.
- A lot of things are implemented as a personal preference and I am sure there are much better ways to do these. So, if you find something like that, please comment below and I would love to talk more.
- Please don’t use this code anywhere important. This is a warning, this is not going to be one of those posts where you can directly copy paste code, so I really wanna put this out there, don’t use this code anywhere important. Its just for fun and experiment.
Description
Now then let’s start with the real business. In this article I want to setup a basic node “HTTP” server and construct a mechanism to do routing. Ohhh so I just remembered, there is a prerequisite to this and you must have a bit of Node knowledge going forward.
As you can see that first we import the “http” module and then we call the createServer
function which return a refernce to the server we are creating. This takes a function as argument with two parameters which are request and response. The request argument(Object) has all the information about the request some client did to our server and response(Object) is a set of tool by which we respond to those requests.
So, lets leave that for a second and jump to the last few lines of the code. Here we see app.listen
function being called. What this function does is that it binds our above created server to a PORT which in lame terms gives us an address on which others can communicate with us. This other parameter is just a callback function which is called when the binding is done. This is often used a visual indicator to tell us when can we talk to our server.
Now back to createServer,
whenever a client makes a request to our server this method is called. This can be thought of the main of your node app. So, in our most basic version, what we are doing is we are setting the Header of the response object as 200 with contentType as text/html. Which combined means that the data is OK and in the form of either text or html. And we are sending Hello World to each client as a response. The data here is in text format but you could also send html data (for example res.write(<p>Hello World</p>
). You can also use multiple write calls and all before res.end()
gets sent to the user. Now if you save the above code in a file called index.js
and run node index.js.
You should see a console message in your terminal window saying your server is running on PORT 5000(in most case, for the rest whatever it says is right).
Let’s Test
Go to your browser and type localhost:5000(locahost:PORT)
there you should see hello world on the screen. Hurray!!, you made your own server. That wasn’t hard was it ???.
Now that the excitement is gone, you might start to see some odd things here. If you go to localhost:5000/a
, you will see the same thing as on localhost:5000/b
. This is because whenever the user does a request we send them the same data, no matter what the requests looks like, but that’s not really how servers work. What requests are, in simple sense is a mechanism for clients to ask for certain things from the server and thus we need to somehow to modify our response based on the request made by the client. Well the Solution comes up next.
Routing (First Component of our Framework)
Let’s assume that we have 3 end points (/,/about,/contact)
as three pages in our small app. Now, we want to send 3 different html pages to the user when they visit a specific end point. For that we will build our own routing mechanism as Node doesn’t come with one.
So, somethings which we will need to do are:-
- What resource are being requested.
- Corresponding response for that request.
- Also, we wanna make this so that we have a mechanism to adding new routes(endpoints) in future if we want to.
Let’s take a look at the above code and analyze what’ happening. So, we start up top and we see the “http” module, then lets just jump to the bottom to our “createServer” function which is the starting point of our app. There we see it different from the previous version. So, now what we are doing is, we are extracting the url from the request. This URL is used by the user to request different response. Add a console.log(url)
and hide the two lines under that. Now start the server using node index.js
and again try to visit various endpoint, you will see that you get things like “/” when you visitlocalhost:500
or “/about” when requesting localhost:5000/about
. Now, once we know that, lets take a look at the other line. Now we call a strange function called match, which takes two parameters router, url.
Now router is supposed to have routing information or various endpoints and match is used to match the right endpoint for a specific request and then send that data. So, the idea here which I am using is to create an array of objects called router. Now each object in the array represents an routing object, which as two properties, url and fn.
The value of property url is the url which this routing object is for and fn is a function that will be executed when that endpoint is called. Now, if you take a look at match function under the router array, what this match function is doing is it looks over all routing objects in the router array and tries to see if the url property of the routing obj matches the url requested by the user, if so then it returns the corresponding function. If there is no match found then it returns a default response for all other routes. Now that return value is stored inside a variable called m, which is passed the request and response object so that the function can communicate with the client.
Now if you uncomment all the code and run it again using node index.js
, then you can go into your browser and try visiting various urls and see what happens. Now what if I want to add a new endpoint for say products, then you already know what you need to do if you have made it this far. And that it, we officially have routing in our app. Hurray !!!!!!!
This is it for this article. In the next one, I will talk about using .html
files and also other formats like images, etc. We will also talk about various types of resources (static and dynamic) and start to structure things in some formal order.
Your each 👏 would motivate me to write more helpful articles and make open source contribution. You can further connect with me on Twitter, Instagram, GitHub, Facebook and LinkedIn. I would love to talk more about this or some other topic. And most importantly, if you find any issue or have a better approaches please let me know so that we can improve this.