[0:00]It's 2009. The web is getting cooler by the minute. Websites are no longer just static pages but interactive playgrounds. But behind the scenes there's chaos. JavaScript, the star of the show, is stuck in the browser, while the backend is a mess of slow, clunky tech. Websites are laggy, servers are sweating, and real-time apps? Forget about it. It's like trying to run a marathon in flip-flops. Then, out of nowhere, Ryan Dahl, a software engineer, drops a bombshell. What if JavaScript could escape the browser and run on the server? So here comes Node.js, a JavaScript runtime that allows you to run JavaScript outside the browser. From Netflix to NASA, it's mainly used for backend development like server-side programming to handle requests, databases, and APIs. It's fast, lightweight, and efficiently handles multiple requests, leading to a huge community that loves it. To start learning and using Node.js, we first need to install it from nodejs.org/en/download where we can get the latest version of Node. After that, open your favorite code editor and type the following in your terminal: npm/v. This should display the installed version, meaning our Node.js is now ready. But there are situations where the ability to switch between different versions of Node.js can be very useful. For example, if you want to test something you're developing with the latest bleeding edge version without uninstalling the stable version of Node, Node Version Manager can help with that! After installing Node.js on our system, let's build a simple Node app. First, let's create a file named app.js in our project folder, and inside it, let's write console.log Hello, Node.js with a party popper. After that, let's open our terminal and run this file by typing node and then app.js. Congratulations, you just built your first Node.js app! Now, to truly understand how Node.js works, let's explore what happens behind the scenes. When you run node app.js, Node.js starts by reading your JavaScript code. This code is processed by the V8 engine, which is the core JavaScript engine developed by Google and embedded within Node.js. This compilation process enables JavaScript to execute at near-native speeds, making it incredibly fast. Once the code is compiled, Node.js executes it within its runtime environment. Node.js also leverages the libuv library to handle asynchronous operations such as file system access, networking, and timers, using an event-driven, non-blocking architecture. This non-blocking behavior is what makes Node.js highly efficient for handling IO heavy operations. For example, consider the following code: When this code runs, the event loop follows these steps: The event loop first executes the synchronous code, printing start and end to the console. After that, the set timeout and fs.red file functions are asynchronous. Node.js offloads these tasks to the system kernel and continues executing the next lines of code without waiting for them to complete. The event loop then enters its phases. It checks for pending tasks in each phase and executes their associated callbacks. For instance, in the timers phase, it checks if the one-second timer set by set timeout has expired. If so, it executes the callback, printing timeout. In the poll phase, it checks if the file reading operation has completed. If so, it executes the callback, printing file read. If there are no tasks in a phase, the event loop moves to the next phase. It continues running as long as there are tasks to process or timers to wait for. Once all tasks are completed and no more events are pending, the event loop exits, and the program ends. This demonstrates how the event loop enables Node.js to handle asynchronous operations efficiently, ensuring that the main thread remains unblocked and responsive. By leveraging the event loop, Node.js can manage thousands of concurrent operations, making it ideal for building scalable, high-performance applications. Now you might wonder why is this important to understand? Many bugs in Node.js applications stem from misunderstandings about asynchronous behavior. For instance, if you don't grasp how the event loop works, you might accidentally block the main thread with CPU intensive tasks, causing delays and overloading the event loop with too many callbacks or tasks. This can lead to performance bottlenecks. And that's how Node.js works in a nutshell. But you're here to build an API and start your backend development journey, right? Let's then first start creating a simple API. We're going to keep things super simple, just a basic GET route that returns a list of tasks. This will give you a solid understanding of how the backend handles requests and sends responses. We'll create a tasks.js file that holds our data. Inside, we'll define an array of tasks. Each task will have an ID, a title, and a completed status. The tasks file will be used to store the data and export it to our main server.js file. After that, let's import the modules we need, like the HTTP module from Node.js and our tasks. The HTTP module allows us to create an HTTP server that can listen for requests and send responses. Next, let's declare a constant variable named server and then call the HTTP create server function. This will allow us to create our server. Inside that, let's provide a callback function with the arguments of request and response. If you didn't know, the request object will contain information about the incoming request, like the URL and method. The response object is used to send data back to the client. This is where the frontend can tap into your server, such as using fetch or Axios, which will dictate the type of request or which API it will call. But don't worry, you'll understand these concepts more thoroughly later in the video. After that, inside the callback, let's set what type of request this API will handle. So, let's declare an if-else statement. We know that this server will only accept GET method requests. So let's make sure the request method we're receiving is GET. But we also need to specify where we will get the data from, which API route the server should listen to. In our case, we need to check if the request is for the tasks route. If the request matches, the server proceeds to send a successful response. For example, res.writeHead sets the response header. The 200 status code means okay, and the content type is set to application/json, because we are sending JSON data. Meanwhile, res.end sends back the task we created earlier. But what if the request doesn't match the /tasks route or method? Well, let's just return a 404 response header indicating that the requested resource was not found. Then res.end will send a JSON message with the key message and the value not found, telling the client that the requested route doesn't exist. After that's done, let's also make our server listen on a port. For example, this starts the server and tells it to listen for incoming requests on port 3000. To run our server, let's write node server.js in our terminal. You will then see the console log you set earlier, indicating that your server is running. This means that when you visit localhost on port 3000 and then a pen/tasks, the server will serve the data we created. To simplify testing, let's use a REST Client API extension! Any client works, but Echo API excels for testing and documenting this API. Since we're listening on port 3000, enter http localhost 3000 in the URL box. And of course, to connect to our API, which is on the /tasks route, we just add /tasks to the URL. When you click send, it will fetch the data we want, and that's how we build an API in Node.js. But what if we could make it more modern and even simpler? Well, that's where Express JS comes in. A Node.js framework that makes building APIs easier and more efficient. It's like a helper that takes care of the tricky stuff, so you can focus on making your app work the way you want. With Express.js, you can set up a server fast, handle requests from users, and keep everything running smoothly. For example, what if we could simplify it? What if the server just handled GET requests without needing an if-else statement and worked with requests and responses like this? And then, what if we could remove write head and make it even shorter? Well, we can do that with Express.js! Let's first install Express by typing this in the terminal: npm install express. Once that's done, you can use import Express from Express in your code, and we can use the Express package with our server constant like this. Revisiting Echo API and testing the /tasks route again, we fetch the same data with 80% less code. Express.js keeps API development clean despite managing multiple routes. For instance, imagine you're building a simple inventory web app. You have a list of items, like products in a store, and you want to show them through an API. With Express.js, it's super easy to set that up. Let's say your inventory looks like this. Inside inventory.js, you have an ID, a name, and a quantity. In real-world development, instead of getting data from a file, you would connect to a database like MongoDB or MySQL, and work with it. We'll create videos for that soon, so stay tuned! Now we can use Express.js to get this list when someone visits a route, like /inventory. Like we did earlier, we just create a constant and connect it to the Express package. After that, we specify what type of endpoint this server will use. In this case, it's the GET endpoint. Then, we wrote our GET endpoint to /inventory, send a JSON response to anyone who requests this route, and make our server live by having it listen on port 3000. When we test this using Echo API, we can now get the inventory data. Just go to http localhost 3000/inventory, and you'll see the list. But what if we also want to add more products to it? Let's make it so anyone can send new items to our inventory. We can use a POST method for that. Like earlier, the GET method grabs data from the server, but a POST method sends new data to the server to add something, like adding a new item in our case. It's just like how you post a new photo on Instagram. The photo you send gets added to the server Instagram is connected to. To make a POST endpoint for our inventory web app, we can simply use the POST method and route it to /inventory. And here's the magic: since we're adding a new item, we need to make sure we store the request that the user sends us. So, how do we use the request? In Express.js, the request is stored in something called req, like we discussed earlier. When someone sends a POST request with data, like a new product, Express puts that data in req.body. Let's then store the request body in a constant. But for req.body to work, we need to tell Express to understand JSON data first. We do that with server.use and then express.json(). Think of server.use function as a way to plug in a helper to your Express app. It's like saying, before handling any requests, use this tool I'm giving you. It sets up something that runs for every incoming request. In turn, express.json is a middleware that parses incoming JSON data and converts it into a JavaScript object. It's similar to how we manually set the content type and used JSON.stringify in vanilla Node.js, but now, Express automates this for us. Then, let's attach an ID to the new item, and after that, add the new item to the inventory array. Let's also send back a response to make sure the user who uses our route knows it was successful. Let's then test our newly created POST endpoint. Start the server with node server.js. Then head to Echo API. This time, instead of /tasks, we will append /inventory because that's what we are looking for. After that, let's also change our HTTP method to POST, since we want to hit the POST endpoint. Since we are posting something, we need to send some data. We can do that in the body. Let's make it raw JSON. Since our inventory consists of a name and quantity, we can provide an example like oranges with a quantity of 20. And since we are automatically handling ID creation, we don't need to add an ID to it. After that, let's click the send button and look at our response view. You can then see what this line of code does. It will display a product added message along with the item data. Need fresh product names? Echo API's dynamic values section generates mock data like random fruit names. Click send repeatedly to see new fruits in the response. This boosts continuous post testing. Next, fetch it in Echo API to confirm new data creation. Now that we've added new changes to our server, we need to restart it! This is very inefficient, right? Well, thanks to the huge community that loves Node.js, we have Nodemon. Nodemon is a tool that helps build Node.js apps by automatically restarting the app when it notices file changes in the folder. We can install it in our project by typing npm install nodemon. Then, let's go to our package.json file. The package.json file is like a list that tells our project what tools it needs and how to use them. It's super important for keeping everything organized. Now, in the package.json file, find the part that says node server.js and change it to nodemon server.js. After that, go to the terminal and type npm run start. This will be our default command to run the server. Test the GET route in Echo API to retrieve the two fruits added to inventory. You might wonder, where's the data we sent earlier in our POST request? Well, that's where databases come in. Since we're just testing our endpoint, our data isn't really stored permanently. That's why every time we restart our server, the new data disappears. But thanks to Nodemon, we don't have to restart our server every time we add a new API or make changes in our folders. Now, let's make things even better. We can add a PUT route to update our inventory, just like how you edit a Facebook post because of bad grammar. A PUT route lets us send new data to replace what's already there. For example, if we want to update the number of apples in our inventory, we can use a PUT request to send the new info. This makes our app more flexible! Let's improve our server by adding a PUT route. Then, we'll route it to the inventory and add our request and response parameters. For our PUT route to work, we need to understand its concept thoroughly! If you want to update an item, you need some kind of identification to specify which item to update, right? For example, when schools update a student's grade, they usually find that student's record using an ID. Well, our inventory also has an ID, and this is an important concept when working with dynamic routes. Dynamic routes allow us to create flexible URLs that change based on the data we are working with. For example, instead of writing a separate URL for every item with the ID we wanted, we can use a single dynamic route that updates any item based on its ID. The semicolon you see here shows that this route is dynamic. It helps get the changing data that users type in. For example, with localhost 3000/inventory/1, you can get the ID of one. To do that, you use the request.params property to name the ID. In our case, this will be the ID. After we get the ID we need, let's find it in our inventory database example. If we didn't find it, let's send a response message that the item is not found. But if we do find it, let's assign the new data from the request body and send a message item updated. Now, let's test our new route using Echo API. Just input our route with the ID of one, then change the method to PUT. Next, write the fruit name and the quantity to update in the body. Say, 25 this time. Hit send, and tada, you've created an update route! But what if you accidentally post a new item that is not a fruit? Well, you can also create a DELETE endpoint. As it name suggests, a DELETE endpoint is a feature in a server's system that allows you to remove a specific item from a database or list. Since we also need to specifically remove a specific item, we would need to use a dynamic route and then store it again in a constant, using the params property from request. After that, let's find the item and use an if-else statement. If we don't find the item, we'll respond with a message saying, item not found. However, if we do find it, we'll remove the item from the array using the splice method and respond with a message saying item deleted. If we test this route with Echo API again, we'll receive the message item deleted, confirming all API routes work! If you didn't notice, we just built a full REST API in Node.js, using the Express.js framework. This will enable you to build much more complex backends by mastering these concepts. All of these concepts are fundamental, though they may differ slightly for every database out there, such as MongoDB or MySQL. Now, let's make testing smoother. Set up automation to prep requests like generating random data. Imagine setting a random quantity like 50 for an item like Apple, skipping manual entry. Server response? A post-response step grabs the ID from your post, safe for an item with a quantity, use it in a PUT method to inventory/1 to bump it to 25. Check the 201 status-or flag weird quantities. No more tedious typing, just slick testing! And if you want a neat trick, you can bundle your GET, POST, PUT, and DELETE requests for /inventory into one set. Name it Inventory API Test Suite. Run them all at once, watch the responses flow, and spot any glitches fast. Now, if you want to deploy the API you just built, you can use platforms like Heroku, Vercel, Google Cloud, or AWS. Need API documentation for your users? Use Echo API's design tab to create it from your HTTP requests. Try this, make a POST inventory request file with a body like oranges and a quantity of 40. Send it to see the response. Then, in the design tab, click Pull from Debug, pick POST Inventory, and you'll get a schema with name and quantity. Click share for an instant shareable document. Easy workflow with Echo API. And I know we covered a lot of topics today, which is why we created a PDF version of this video. It's free, but we'd really appreciate it if you supported the channel. This is just the basics of Node.js with Express.js. We would still make in-depth videos covering every database out there. Well, that's it for now, Novas. Thank you for watching!
Watch on YouTube
Share
MORE TRANSCRIPTS



