{"resource":{"author":{"id":"h2so9H8jPMmgUKGghoNl","name":"Yomesh Gupta","username":"yomeshgupta"},"content":{"link":"https://devtools.tech/build-your-own-express-js-part-one/","difficulty":2,"domain":3,"type":1,"isInternal":true,"body":"This is going to be a multipart series in which we are going to build a minimal, simple and yet powerful version of [Express.js](https://expressjs.com/), called [Minimal.js](https://github.com/yomeshgupta/minimaljs.git). We are going to talk about Node.js in-built modules, HTTP server, routing, middlewares, and much more.\n\nWe are learning on the go so if you find any mistake or any better way to do certain things or just want to share your feedback then I am all ears and open to collaboration. [Let me know your opinions here](https://www.twitter.com/yomeshgupta).\n\n## Introduction\n\n[Express](https://expressjs.com/) has become the de-facto standard framework for web server applications in Node.js. It is easy to use, has a low learning curve, exceptionally well plug & play middleware system and it's minimal by design. As its homepage says,\n\n> Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.\n\nIn this series, we are going to build a similar (but quite simpler) web framework like Express. Our architectural decisions and API design will be as close to Express as possible. However, some implementations would be different so take it with a pinch of salt. :P\n\n## Prerequisites\n\n1. Latest stable version of Node.js installed\n2. A Basic understanding of JavaScript and Node.js runtime.\n\n## Part 1\n\nThis part would be a very simple introduction to Node.js modules, HTTP and we are going to create a basic server from scratch. If you already know all this then you can skip this one and move to [part 2](https://www.devtools.tech/resources/s/build-your-own-expressjs-or-part-2---rid---negw30VulwpaVLRpxxMl).\n\nI would recommend that you should code along. So, go ahead, clone the repo and check out the `start` branch\n\n```\ngit clone https://github.com/yomeshgupta/minimaljs.git\ngit checkout start\n```\n\n### HTTP\n\nThis page is generated by a mix of HTML, CSS and JavaScript, sent to you by Devtools via the internet. Internet is full of pages like this and a lot of cat pictures. A LOT! 🐱 These pages are hosted on different servers all around the world. When we visit the internet and access any content, our browser must ask the servers for the content it wants and then display it to us. The content here is also known as a resource that can be of varied types such as HTML files, images, videos, scripts and many more. The protocol which governs all this communication is known as HTTP.\n\nHTTP stands for `Hypertext Transfer Protocol (HTTP)`. It is a protocol that is used to structure communication between client and server. The client requests the server and the server provides the apt response. It is a stateless protocol i.e. two requests to a server are mutually exclusive and the server does not keep any data between those requests.\n\nThe transfer of resources between server and client happens using `TCP (Transmission Control Protocol)`. When you type an URL such as [www.devtools.tech](https://www.devtools.tech) into your browser then you are asking it to open a TCP channel to the server that resolves to that URL. The server receives the request, processes it, sends back the response to the client (your browser) and closes the connection. When you again open the URL then the entire procedure is followed again.\n\nHTTP defines a set of request methods to indicate the desired action to be performed for a given resource. They are commonly referred to as HTTP verbs. I am listing some verbs below:\n\n1. `GET` - Requests made to retrieve data.\n2. `POST` - Requests made to submit data to server, resulting in the change of state or side effects on the server.\n3. `PUT` - Requests made to replace all current representations of the target resource with the request payload.\n4. `DELETE` - Requests made to delete the specified resource on the server.\n\nComplete list can be found [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods).\n\nJust like the requests method, we have response status codes which are important for interpreting the server's response on the client-side. Some of the status codes are\n\n1. `200` - Successful\n2. `404` - Not Found\n3. `500` - Internal Server Error\n4. `301` - Redirect\n\nComplete list can be found [here](https://httpstatuses.com/).\n\nTo read more about HTTP, check out this [MDN resource page](https://developer.mozilla.org/en-US/docs/Web/HTTP).\n\n### Let's build\n\nNode.js provides a lot of powerful modules built-in; [HTTP](https://nodejs.org/docs/latest-v10.x/api/http.html) is one of those modules. As docs put it,\n\n> The HTTP interfaces in Node.js are designed to support many features of the protocol which have been traditionally difficult to use.\n\nWe are going to require `http` in our `server.js`\n\n```js\nconst http = require(\"http\");\n```\n\nIt provides us with a method `createServer` which takes a callback `requestListener` as an argument and returns a new instance of `http.Server`. Let's use this.\n\n```js\nconst http = require(\"http\");\n\nconst server = http.createServer((req, res) => {\n  // request handling\n});\n```\n\nNow, we the `http.Server` instance in the `server` variable. Calling, the `listen` method on it will allow our server to receive requests as in it will bind the server to a port and listen for incoming connections.\n\n```js\n...\nconst server = http.createServer((req, res) => {});\n\nserver.listen(8080, () => console.log(\"Server running on port 8080\"));\n```\n\nBy doing this much, our server is live! However, what to do when an actual request comes in?? How to handle that?\n\nThe `requestListener` we talked about earlier is the one that executes when a request comes in. It receives two parameters:\n\n1. `request` object contains information about the current request such as URL, HTTP headers, and much more.\n2. `response` object contains methods that are used to send data back to the client.\n\n```js\n...\nconst server = http.createServer((req, res) => {\n  res.writeHead(200, {\"Content-Type\": \"text/html\"});\n  res.write(\"Hello world\");\n  res.end();\n});\n...\n```\n\nIn the above code snippet,\n\n1. We are calling `response.writeHead()` which sends an HTTP status code and a collection of response headers back to the client. Here, we are setting `statusCode 200` and `Content-Type: text/html`.\n2. We are calling `response.write()` which is used to send data to the client.\n3. By calling `response.end()`, we are informing the server that response headers and body have been sent and the request has been fulfilled. The server closes the connection after this method call.\n\nLet's refactor a bit and create a `config.js` file to store our app's configurations.\n\n```\ntouch config.js\n```\n\nAdd the following code to it and require it in our `server.js`\n\n```js\nmodule.exports = {\n  PORT: 8080, // or any other port you wish to run your server on\n};\n```\n\nThe road so far...\n\n```js\nconst http = require(\"http\");\nconst { PORT } = require(\"./config\");\n\nconst server = http.createServer((req, res) => {\n  res.writeHead(200, { \"Content-Type\": \"text/html\" });\n  res.write(\"Hello world\");\n  res.end();\n});\n\nserver.listen(PORT, () => console.log(`Server running on ${PORT}`));\n```\n\nOur server works so far and we have implemented a catch-all route that serves the same `Hello World` content for any URL you visit on the server. Let's make it a little nice and show some actual good old HTML. 😄\n\nCreate a `public` folder in your root directory and inside that folder make an `index.html`\n\n```\nmkdir public\ncd ./public\ntouch index.html\n```\n\nAdd the following Html to index.html\n\n```html\n<!DOCTYPE html>\n<html>\n  <head>\n    <title>Minimal.js | Part 1</title>\n    <style>\n      * {\n        margin: 0px;\n        padding: 0px;\n        font-family: \"Roboto\";\n      }\n      html,\n      body {\n        width: 100%;\n        height: 100%;\n      }\n      body {\n        background-color: #ececec;\n        background-image: url(\"http://wallpaper.yomeshgupta.com/images/5.jpg\");\n        background-size: contain;\n        background-position: center top;\n      }\n      h1 {\n        max-width: 400px;\n        margin: 0 auto;\n        padding: 40px 0px;\n        font-size: 18px;\n        text-align: center;\n      }\n      a {\n        color: #f67b45;\n      }\n      a:hover {\n        color: #227093;\n      }\n    </style>\n  </head>\n  <body>\n    <h1>\n      Hello World. To see more wallpapers like this and make your new tab more\n      delightful. Check out this\n      <a\n        href=\"https://chrome.google.com/webstore/detail/backdrops/beanogjmmfajlfkfmlchaoamcoelddjf\"\n        >Chrome Extension</a\n      >.\n    </h1>\n  </body>\n</html>\n```\n\nNow, let's require two Node.js in-built modules, `fs` and `path`\n\n```js\nconst fs = require(\"fs\");\nconst path = require(\"path\");\n```\n\n`fs` module is the File System module that provides an API for interacting with the file system. If you want to read any file, write to any file, make a directory, change permissions or anything else file system related; `fs` is THE CHOSEN ONE.\n\n`path` module is a collection of utilities that helps while working with the file system. It provides capabilities like resolving a path, finding directory names, finding extensions of a given file/path and so much more!\n\nUse these modules to read and serve our newly created index.html to incoming requests\n\n```js\n...\nconst fs = require('fs');\nconst path = require('path');\n\nconst server = http.createServer((req, res) => {\n  fs.readFile(path.resolve(__dirname, 'public', 'index.html'), (err, data) => {\n    res.setHeader('Content-Type', 'text/html');\n    if (err) {\n      res.writeHead(500);\n      return res.end('Some error occured');\n    }\n    res.writeHead(200);\n    return res.end(data);\n  });\n});\n...\n```\n\nHere,\n\n1. We are using `fs.readFile()` method to read the contents of our `index.html`. It takes two arguments, `file path` and `callback` which will be executed once the file is read.\n2. In our callback, if we encounter any error then we are sending an error response else we are serving index.html's content.\n3. We are also using `path.resolve` to find the exact location of index.html on the disk.\n\nYou can read about these modules [here](https://nodejs.org/docs/latest-v10.x/api/).\n\nPhew! Our first part is over. We, now, have our first without express HTTP server up and running! In part-2 we are going to take this up a notch and will start working on our framework. Stay tuned!\n\nThe complete code for this part can be found in this [Github repo](https://github.com/yomeshgupta/minimaljs/tree/part-1).\n\n> Wallpaper used in the example here comes bundled with a super amazing minimal chrome extension, `Backdrops`. Check it out [here](https://chrome.google.com/webstore/detail/backdrops/beanogjmmfajlfkfmlchaoamcoelddjf).\n","languages":[],"editorConfig":{}},"stats":{"views":20362,"used":0,"likes":0},"description":"","published":true,"isActive":true,"tags":["node.js","express","rest","api","framework","backend","tools","devtools","framework development","build express"],"slug":"build-your-own-expressjs-or-part-1---rid---qoos1dgnByAcEaCp2rbl","isPremium":false,"categories":[],"requires":[],"_id":"5f1dd63acbec5f7ffc0c2faa","title":"Build your own expressjs | Part 1","resourceId":"qoos1dgnByAcEaCp2rbl","createdAt":1595790906127,"modifiedAt":1643031372431},"currentUser":null,"isOwner":false,"recommendations":{"questions":[{"_id":"66228b6d4079503047f670ed","content":{"languages":["react","html"],"difficulty":2},"tags":["javascript","frontend","ui","atlassian","ux","devtools tech","coding","frontend challenge","blog","tutorials","google","trees"],"slug":"how-to-build-a-confluence-like-sidebar-with-tree-structure-or-atlassian-frontend-interview-question-or-react-js---qid---3r7988VsESMQBt9vP1Zi","title":"How to build a Confluence-like Sidebar with Tree Structure? | Atlassian Frontend Interview Question | React.js","questionId":"3r7988VsESMQBt9vP1Zi"},{"_id":"63907636937c6f5491665d1c","content":{"languages":["react"],"difficulty":1},"tags":["javascript","frontend","code","useCopy","useCopyToClipboard","copy text.custom hooks","react hook","frontend coding","javascript interview question"],"slug":"how-to-create-usecopytoclipboard-hook-in-react-js-or-javascript-interview-question-or-frontend-problem-solving-or-custom-react-hooks---qid---d6Yk9gGqeRevQhhe1UrI","title":"How to create useCopyToClipboard hook in React.js? | JavaScript Interview Question | Frontend Problem Solving | Custom React Hooks","questionId":"d6Yk9gGqeRevQhhe1UrI"},{"_id":"67e53e9c347ebdb1a74b907c","content":{"languages":["javascript","typescript"],"difficulty":2},"tags":["javascript","amazon","frontend interview question","ui","ux","javascript promises","blog","amazon interview question"],"slug":"implement-promisify-polyfill---qid---GFqT2ainSIGaPNODqoDe","title":"Implement Promisify Polyfill","questionId":"GFqT2ainSIGaPNODqoDe"},{"_id":"69a5900c92f33c7d8a9f8e41","content":{"languages":["react"],"difficulty":2},"tags":["javascript","ui","ux","devtools tech","coding challenges","frontend"],"slug":"file-explorer-ii---qid---Xjox8jBBhp2RtuxcbxNK","title":"File Explorer II","questionId":"Xjox8jBBhp2RtuxcbxNK"},{"_id":"645e244cd12c1e2402019e67","content":{"languages":["javascript","typescript"],"difficulty":1},"tags":["frontend","code","programming","lodash","polyfill","lodash once","javascript interview question","ui","ux","devtools tech","codedamn","egghead","frontend masters","problem solving","frontend interview questions","underscore","geeksforgeeks","rate limit","lodash before","limit js function invocation"],"slug":"implement-a-function-that-accepts-a-callback-and-restricts-its-invocation-to-at-most-n-times-or-lodash-polyfills-or-frontend-problem-solving---qid---ge3cwzQQrMlXt6VwDpNg","title":"Implement a function that accepts a callback and restricts its invocation to at most N times | Lodash Polyfills | Frontend Problem Solving","questionId":"ge3cwzQQrMlXt6VwDpNg"}],"resources":[{"_id":"69831e01895fc3bf013c2a19","content":{"difficulty":4,"domain":2,"type":1,"isInternal":true,"languages":[]},"tags":["javascript","ui","ux","devtools tech","coding","frontend interview","coding rounds","tutorial","frontend interview experience"],"slug":"microsoft-frontend-interview-experience---rid---XTc4tJoPszAFovxvJjRX","title":"Microsoft Frontend Interview Experience","resourceId":"XTc4tJoPszAFovxvJjRX"},{"_id":"6310505a77f9961d5b7ce983","content":{"difficulty":2,"domain":1,"type":2,"isInternal":false},"tags":["javascript","redux","react","youtube","interviews","frontend","interview preparation","tooling","state management"],"slug":"build-your-own-redux-or-part-1-or-advanced-frontend---rid---MNkFAzvLnmds66wD3JV0","title":"Build Your Own Redux | Part 1 | Advanced Frontend","resourceId":"MNkFAzvLnmds66wD3JV0"},{"_id":"66a4ca5daac82a58634c2bfe","content":{"difficulty":4,"domain":2,"type":1,"isInternal":true,"languages":["undefined"]},"tags":["javascript","frontend","ui","ux","coding","atlassian","frontend coding challenge","feature flags","interactive shape"],"slug":"top-atlassian-frontend-interview-questions-and-process---rid---Bu7bJx9jNVoIsrH71Byb","title":"Top Atlassian Frontend Interview Questions and Process","resourceId":"Bu7bJx9jNVoIsrH71Byb"},{"_id":"6731bf5cd34d7f4b8cccbdec","content":{"difficulty":4,"domain":1,"type":1,"isInternal":true,"languages":[]},"tags":["javascript","frontend","coding","ui","ux","developer tools","youtube videos"],"slug":"how-to-become-a-better-software-engineer---rid---4lmB97aZrn9z5q00FKZz","title":"How to become a better Software Engineer?","resourceId":"4lmB97aZrn9z5q00FKZz"},{"_id":"5f2856d6cbec5f7ffc0c2fc4","content":{"difficulty":1,"domain":2,"type":1},"tags":["closure","javascript","es6","nodejs","functions","frontend","js fundamentals"],"slug":"closure-and-this-how-are-variables-resolved-within-a-function---rid---UhIPcUg39ApeirvSiv4a","title":"Closure and this - How are variables resolved within a function?","resourceId":"UhIPcUg39ApeirvSiv4a"}]}}