Transcript for:
Node.js Crash Course

What's going on guys? Welcome to my Node.js crash course. So I like to revamp these every few years or so. It's been about three years since the last Node.js crash course and I'll go over what I'm going to cover in a few minutes but I just want to say that this is for all skill levels because we're not using any frameworks like Express and when you build an app or an API, 99% of the time you use a framework like Express or Fastify or Adonis or something like that. which really makes things easier and gives you the tools to create routes and add middleware and just makes things a lot easier. Now this video is much more low level so we're gonna we'll do things like create a server, explore the HTTP module as well as other core Node.js modules. So even if you have experience with say Node and Express there's probably going to be some things here that you haven't really worked with and if you're an absolute beginner it's a good start to just learn Node by itself. and know what it's capable of. All right, so sit back. I would suggest following along just because I think that you can learn a lot more that way. But if you wanna just watch, that's fine as well. So we're gonna just spend a couple minutes on some slides and then we'll jump right into the code. Okay guys, so before we get started, let's define what Node.js actually is. So, many absolute beginners think that Node.js is some kind of framework or library or even a language, but it's not. It's a JavaScript runtime. And a runtime is a program or an environment that runs other programs. So, we can build JavaScript applications and run them right on your computer or right on the server. Now, Node.js was built with C++ and it uses the powerful V8 JavaScript engine. And... that's also used with the Google Chrome web browser. Node.js can be used for a lot of things, but it's mostly used for developing server-side and networking applications, APIs, microservices. It essentially allows you to use JavaScript to write server-side code and do a lot of the same things you would do with Python or PHP or C-sharp and other server-side languages. Now, traditionally, JavaScript was only used on the client side in the web browser to do things like form validation, animation, small stuff like that. But with Node.js, JavaScript has really become a truly powerful full stack language. And again, you can do a lot of the same things you can do with other server-side languages. And there are actually other JavaScript runtimes such as Deno and Bun.js, and those are really cool to explore. They're much newer technologies, but they don't really have a space in the industry yet. So I would definitely suggest starting with Node.js. I would never suggest that someone start with something like Bun.js or Deno just because it's so new and you're most likely not going to find jobs using those technologies just yet. There's also not really a large community or support for them either. So Node.js is very fast and scalable due to its architecture and the V8 engine. It's also pretty popular. I think it's somewhere something like six point three million websites use node.js And it's used by companies like Netflix uber LinkedIn and in addition to really large companies node is also a really popular option for startups and smaller Projects as well now I won't just want to quickly go over what we're gonna cover in this course and in kind of the order We're gonna do it in so of course we're talking about now what Node.js is. I'll talk a little bit about how it works under the hood as well. We're going to install it, set up a project, set up the package.json, which is a kind of like a manifest file. We're going to look at some custom modules, which are basically just files that we can create, and we can import and export functions and data from those files to and from those files. And there's really two module systems that we can use. There's CommonJS, which is kind of Node.js's... native system and then you can also use ES modules which is the import syntax that you use with react view and all the front-end JavaScript stuff so I'm gonna show you both but ultimately we're gonna stick with ES modules that's just what I prefer it's more modern now when it comes to the the core modules that that node includes I think the HTTP module is one of the most important to kind of understand when you're getting started This is what allows you to create a server and accept requests and give responses So a big part of this tutorial will be using the HDP module now in real life Like I said earlier you'd probably use something like Express Which is a web framework that makes things much easier? And I'm also going to be revamping my Express crash course as well But Express uses or sits on top of the HDP module So it's good to know how this works and how to accept requests how to work with them how to send responses back, send JSON back, and deal with HTTP headers and methods and all that stuff. So that's really what we're going to cover in this course or in that part of the course. We're even going to look at some custom middleware, which are functions that sit between incoming requests and outgoing responses. Now when it comes to some of the other core modules, we're going to be going over those in the second part of the course. So the file system module, path module, URL, events, things like that. So I'll cover the basics of all those as well. Now, one common mistake that I see people do is jump to Node.js too quickly. Before learning Node.js, you should have a good understanding of JavaScript. So, of course, you should know all the fundamentals, variables, functions, loops, objects, classes. You should have a good understanding of that stuff, most definitely. Now, I'd also suggest that you understand asynchronous programming, so you should know things like callbacks, promises, the async await syntax. Chances are you'll be building web applications and JSON APIs with Node.js, so you should understand how HTTP works, the request response cycle, you should know about HTTP methods like GET, POST, PUT, DELETE, you should know the common status codes 200, 404, 500, things like that, and you will be learning more about this stuff as you learn about Node.js and even in this very video. Now, you probably are coming from frontend. JavaScript, so you've probably worked with JSON APIs. You've probably consumed them. Well, now you're going to be creating them most likely. So it helps if you already have a basic understanding of how they work. Like I said, HTTP methods and status codes and all that. And then NPM, the Node Package Manager, you probably have some experience with. I mean, if you're using React or any front-end framework, you're usually installing that stuff with NPM. So you probably have an idea. but you will also learn about NPM and package.json and stuff in this video. Alright, so let's talk a little bit about how Node.js works and I'm not gonna go too deep into this because I want this to be practical and easily digestible, but you should have a basic idea of how Node works under the hood. So, as I said, Node is built on top of the V8 JavaScript engine, which is the same engine that powers Google Chrome. Other browsers have their own engines, like Firefox has SpiderMonkey, Safari has JavaScriptCore. The V8 engine is written in C++, and it's what takes your JavaScript code and converts it into machine code so that your computer can understand. And Node has taken this engine and extended it to work on the server side. Now, Node.js is what we call non-blocking, which means that it doesn't wait around for I.O. operations, which are input-output operations. and those are things like network calls, file system operations, database operations. And instead of blocking the execution of code while waiting for these things to happen or these things to complete, Node.js uses events and callbacks, and this allows it to handle thousands of connections at the same time, and this is why Node.js is so fast and efficient. Now, in Node.js, there's a single main thread that executes your JavaScript code, and you can think of a thread as a set of instructions that your computer executes. And in a single-threaded environment, there's only one set of its instructions that are executed at a time. This is different from multi-threaded environments where you have multiple threads that can execute different parts of your code simultaneously. So Node.js uses something called the event loop, which is a mechanism that allows Node to perform non-blocking I.O. operations. And when you make a network request, for example, Node.js doesn't wait for that request to complete. Instead, it continues to execute the rest of your code. And when that request does complete, it triggers a callback, which is then added to the event queue. And the event loop picks up the callback and then executes it. So I know this is a little tough to understand. So the analogy that I like to kind of describe and what helped me is to imagine the event loop as one of those giant revolving doors at the mall or something like that. and each person represents a task or operation initiated. And as a person walks into the building that's initiating a task, instead of waiting for them to complete their business inside the mall, we'll call that the task execution, Node.js keeps the revolving door spinning, signifying the event loop. Now, as each person finishes their task in the building, they exit the revolving door, representing the completion of their task. And the event loop or the door keeps the flow going, handling incoming tasks and ensuring that the program's execution remains uninterrupted. So when a callback executes in Node.js, it's akin to a person executing that revolving door. And it would mark the completion of their task. And while the event loop keeps processing and flowing, it waits for others to enter. Now, I don't know if that analogy helps or if it just confused you more, but that's kind of how it works. And it's not. that important for you as a beginner to understand how everything works under the hood right now. It's more learning the syntax and how to handle incoming requests and send responses and things like that. Now, as far as what Node is used for, it's used for a lot of things. So of course, building APIs, and this could be RESTful APIs, GraphQL APIs, server rendered apps. So of course, we can serve JSON data, but we can also serve HTML pages and we can use different template engines like EJS, Mustache, there's all types of Engines that you can use to serve HTML pages dynamic pages. It's also great for real-time applications like chat real-time games collaboration tools things like that Microservices so microservices are small independent services that work together I actually just did a crash course on microservices if you're interested command line tools You can build CLI command line interfaces Bots. So, for example, you could build Twitter bot or a bot for Slack or discord web scraping. Node.js is good for web scraping. And there's a few different frameworks that you can use for that as well. And then web servers, of course, and it could be a sophisticated web server handling complex routing and serving dynamic content or just a simple static file server. What Node.js is not great for is CPU intensive applications. So as we talked about, Node.js is single-threaded and uses an event loop, which makes it great for IO operations, but not so great for CPU-intensive operations. So if you're doing a lot of heavy computation and things like that, you probably want to look more into like Python, Ruby, Java, and other server-side languages. But that's it for the slides. Now what I want to do is jump in. We'll talk a little bit about installation, which is very simple, and we'll start to set up a project, and then we'll go from there. Alright guys, so this is the official Node.js website, nodejs.org, and as far as installation goes, it's very simple. If you're on Windows or Mac, you can just simply go to the site, click download, download the LTS, which is the long-term support version. You can download the absolute latest version if you want. There might be some extra features there, but I usually suggest using the LTS. And then you can just run that file. I already have it installed in this machine, so I'm not going to run it. But it's just like any other installer. Just go through it, and then Node should be installed. Now, if you're on Mac, you can also use Homebrew. And, of course, if you're on Linux, you can use your, you know, whatever the package manager for your distro is and get it installed that way. And then you just want to open up a terminal or a command line prompt and just do Node dash dash version. And that will show you the version that's installed. And Node.js comes with NPM, which is the Node Package Manager, which you can use to install third-party packages, and you can just make sure that that's installed as well. Now, Node.js does come with a REPL, which stands for Read, Eval, Print, Loop, and it's basically just a command line environment to run JavaScript. And you can start that by just typing Node and then Enter. So from here, I can type in any JavaScript that I want. Now, you're probably not going to use this much. but it is a nice way to kind of test out code and just experiment with JavaScript and not have to do it through a file through the browser or anything like that. So I'll just give you some examples. We can do a console.log. And obviously when you're doing front-end JavaScript, the console pertains to the console in the browser. This pertains to the terminal. So if we do console.log hello world and run that, it's going to just... Spit it out to the terminal to the console and undefined just means that there's nothing being returned from this line now You can also create variables like we can say name John and obviously I get undefined because that doesn't actually return anything if I do a console dot log of The variable of name then I should see John you can also create functions like I could create We use a one-line arrow function here called greet And we'll just return, let's just return, we can put some backticks in here and say hello, and then put our name variable, and then we can call that function, and we get hello John. All right, so like I said, you're probably not going to use this much, but it is there for you to test out code or whatever you want. So you can just do control or command C to get out of that. Now from here, I just want to create a folder to work in. You can either use your Explorer or File Manager, or you can use the terminal and just do make directory. And I'm going to call this nodejs-crash-2024. Okay, and then I'm just going to cd into that folder. And then from there, I'm going to open my text editor with code dot. If you're not using VS Code, just open that folder up in whatever editor you're using. So close that. And now I'm just going to... use the integrated terminal for any commands that I want to run. Now 99% of the time the first thing you're going to do when you're starting a new Node.js project is create a package.json file. So we can do that by using an npm command. So in the terminal we can say npm init and there's going to be some questions asked and if you wanted to skip those questions you could just add dash y but I'm going to go through those just so you can see what they are. So the package name whatever is in parentheses is the default. So you can just hit enter to accept that version description, I'm just going to say node j s crash course code. Then the entry point which is like your main file index.js That's fine And then you can just enter through this stuff if you want you can put your own name and then for license I usually put MIT and then enter and that will create a package dot JSON file for you So you never have to create this manually and this has you know Basically the stuff that we just that we just answered and then it also has scripts. So basically, you can create what are called npm scripts to do certain things like start your server, stop it, run tests, all kinds of stuff. And I'll get more into that a little later. So now that we have a package.json file, the next thing you would usually do is create an entry point, which is your main file, the file you're going to run. Usually when dealing with Node.js, or any language, really, you're going to have a project structure with files and folders. And usually you have one entry point and the other stuff is just imported into other files. So let's create a file. I'm going to call it index.js and you might see this as app.js or server.js. I usually like to use index. Now from here we can just type JavaScript so I can do a console log. Let's say hello world. Now since we have node.js installed on this machine I can run this file. from my terminal by saying node and then the name of the file which is index.js make sure you're in the correct directory and you'll see hello world printed to the console and you don't even have to do the dot js we could just do index which is the name of the file and then that runs it as well okay and you can put any javascript that you want here okay now there are some differences so for instance when you're in the browser environment and i'm assuming that a lot of you are coming from the front end So in the browser, you have this window object, right? If I were to run it, you'll see I get an error. It says window is not defined. That's because there's no browser. So there is no window object. Now there is something called global, which is similar, but it doesn't, it obviously doesn't represent a browser window. It represents just the global object. And you can see that there's a bunch of stuff on this, on this as well, such as setTimeout, setInterval, these are actually not part of JavaScript. They're part of the web API in the browser, but they're also available in Node.js because of this global object. Now there's also not a document object, so there's no DOM because there's no document. The document pertains to the browser and its environment, so that's not available, but there is a process object, so that pertains to the current process. that's being run so you can see there's a bunch of stuff on here that you can get as well you can get environment variables things like that and i'll talk more about the process later all right so yeah so those are basically it's just the environment is different but as far as the javascript language goes it's all the same and that's what's great about building full stack when you're using like react or view or anything like that you're you're writing the same language on the front end as you are on the back end which is nice rather than doing JavaScript on the front end and then Python or PHP or something on the back end, which is also fine, but I like to have it all in one. Now, I want to talk about modules. So usually, like I said, you'll have a structure of files. So let's go ahead and create a utils.js file. And let's say that this is just a file that has random functions that we want to use around our site. So I'll create a function. Let's call this generate random number. And that's exactly what it's going to do. So we'll make it really simple. We'll just say math.floor. So we're going to round down math.random. And we'll multiply that by 100 and then add 1. So it's basically going to give us a number between 1 and 100. Now I want to be able to use this function in other files. So in order to do that, we have to export it. Now the system that I'm using right now is called CommonJS. It's like the native Node.js module system. And I'm going to show you how to do it with that first, and then I'm going to show you how we can switch to ESModules, which is the more modern syntax that you use with front-end frameworks. So with CommonJS, what we would do is say module.exports, and whenever we want to export, we set this equal to. So let's say generate random number. We don't use the parentheses here. Now, since I exported it, I can import it where I want. So let's import it into this file. So to do that, we'll say const and then generate random number, and then we use the require syntax. That's common js. And then we want to do.slash, which is the current directory, and then utils. And with common js, we don't have to do the.js at the end. So now I should be able to, let's do a console log. We'll put some backticks, and we'll say random. number, and then we should be able to use that function. So now if we run this file with node index, I get random number 67, random number 79, so I can use other functions from other files. And it's not just functions that you can export. You can also export objects or arrays and other types of data. Now... This is what we call a default export because it's one thing being exported. However, you might have other functions that you want to export. So let's create another one. We'll call this Celsius to Fahrenheit. And let's say it takes in Celsius argument. And then let's see, the formula for that is... See that whatever that Celsius value is multiplied by 9 and then divide that by 5 and add 32. So that should give us the Fahrenheit. Now I want to export both of these. So what I need to do is export an object like this and put both functions in there like that. And then when I import it, I'm going to wrap this in curly braces and then I can just. Go ahead and import both and then I'll come down here. We'll do a console log with back ticks. We'll say Celsius to Fahrenheit. I don't know if I spelled that right. And then we should be able to run that function and we'll pass in, let's pass in 32. I'm sorry, passing zero Celsius to Fahrenheit. So that should give us 32. All right, so you can see right here Celsius to Fahrenheit 32. So that's like a quick crash course on CommonJS syntax. Now I want to show you how to use ES modules, which is the import-export syntax. Now there's one thing we have to do in order for this to work, and that is in the package.json file, we have to add in here type, and then we're going to set that. You see we have two options here, CommonJS, which is the default, and then module. So we just have to set type to module and then we can use it. So let's create another file. I'm just going to call this postcontroller.js. So we'll say we're building some kind of blog API or blog app and this will be where we can fetch our posts and stuff. Now usually you'd have some kind of database. You would use a third party package like SQLize or Mongoose to interact with your database. But we're just going to create some hard coded posts. So we'll have an array, an object, we'll just have an ID, and a title. So we'll just say post1, and then we'll copy that down, and this will be post2, ID2. All right, so let's say we want to have a function, and you can use arrow functions as well, of course. So we'll say getPost, and we'll set that to an arrow, and then we'll just return the post. So very simple. Then to export there's a few options we can do this we can simply just put export before it and then in our index.js I'm just going to comment this stuff out. You can just ignore that now so to import we can do this And it's not exported as default so it we need to have these these curly braces around get posts now with ES modules when you're using it with node.js we do have to add the dot.js at least I think we still have to let me just run that yeah so you see how we get an error so cannot find module did you mean to import post controller dot.js so if I do that and I run the file I shouldn't nothing's going to happen because there's nothing here but I don't get the error so I should be able to use this now So we'll come down here and let's just do a console log of get posts. And now we'll run it and you can see it prints the post. Now another way that you can export is at the bottom. So if you don't do it here, get rid of that. We can just do export and then as an object, get posts. We can put that in there like that and it should work again. Now you might want to export it as default. So, for example, when you build a React component in the front end, you usually export that as default because it's usually the only thing being exported from that file. So to do it as default, you would get rid of these curly braces and you would say export default get post like that. Now, if I want to use this, I have to bring it in without the curly braces. So that should work and it does. And you can even export one thing as default and then other things as not default. So let's say we have a, actually we're going to use export here. So let's say we want to export another function called getPostLength. And we'll set that. to an arrow function and we'll just return post dot length okay so that's going to export get post as default and get post length as just regular so here i can put a comma and then have my curly braces and get post length and i should be able to let's console log and say post length and then get post length If we run that, there we go, post length two. All right, so that is using import and export for both common JS and ES modules. I prefer to use ES modules, so we're gonna just use that for the rest of this. So like I said, I wanna jump into the HTTP module and creating a server and dealing with request response. I mean, that's kind of the majority of what you're probably gonna be doing with Node.js. Now, like I said a few times, you're gonna do this. most likely with a framework such as Express or COA or Fastify. There's tons of great frameworks out there. But I think that it's good to know kind of what's going on under the hood. So let's close up Index.js and let's create. And I'm just creating these files just so you have them. I'm going to put them in a repository just so you have them for documentation. But let's create a server.js file. And that will be our new entry point for what we're doing now. And we're going to import the HTTP module. So let's say import HTTP from HTTP. No dot slash or anything like that because it's not a file that we're including. It's a module that's included with Node.js. So we want to create a server, and there's a method called create server that we can use. So we're going to create a variable called server, and then we want to set that to HTTP. And then there's, like I said, a... Method called create server and then that's going to take in a function It doesn't have to be an arrow can be just a regular function if you want now this will have a request so our EQ and a response our ES and These two objects are really important and we're going to use different methods and properties from them But all I want this to do is basically just send some text to the client So we're going to take our response object and there's a right on that And you can see right here, the write method writes some data to the stream and calls the supplied callback once that data has fully been handled. If there's an error, then the callback will be called with the error. And, I mean, you can read all this stuff if you want to really get into it, but we're just sending some text to the client. In our case, it's going to be the browser. So let's just write hello world, and then we want to end the response with res.end. Now, like I said, and I'm probably going to say this a bunch of more times, when you're using a framework like Express, you don't have a responsibility to end the stream. It just does it automatic, all right? Just like you don't have to manually set some header values and the content type and all that stuff. And if you take the Express crash course after this, I think that's a good idea because you can kind of compare the two. So this by itself won't do anything. We have to listen on a port. So we're going to take that server variable, and then we're going to call the listen method. And that's going to take in a port. I usually use 5,000 for server-side stuff, but that's actually being taken up on this machine, so I'm going to use 8,000. And then you can also pass in a function so you can just do something after it connects. So we'll just do a console log, and we'll say server. Running on port and we could we could even make these back ticks. Yeah, let's do that Let's make these back ticks and then we'll actually create a variable for the port So we'll say on port and then we'll put that variable in here and for now We'll set the variable up at the top here. Let's say const port and we'll set that to 8,000 All right, so now we should be able to run our server. It's very very simple server, but We should be able to run node server and now you see server running on port 8000 and it takes up the terminal I can't I can't put any more commands in here unless I shut down the server now Let's open up the browser, and I'm gonna go to Not 5,000 8,000 and we should see hello world. So let's go back to code and we can even get rid of this rez dot right because the end method you can send a response body here so we can actually put our hello world in there and we could get rid of this and we should get the same thing now you do have to restart the server So let's do that and let's reload and yeah, we get the same thing. Now we can also set header values such as content type or you might have like an authorization key or something like that. So we can take our response object and there's a set header method. And let's change the content type. So we'll say content-type and then the second argument we pass in is the type we want let's say text slash html and then down here let's wrap this hello world in an h1 and restart the server and then if we come back here you'll see it's now in h1 and if we open up our dev tools go to the network tab and reload click on this local host You can see it's a get request. It's going to be a 200 response by default. And you can see content type is text HTML. Now I could change that if I did like text plain. That's for plain text. Reload the server, come back here, and now it's actually showing me the h1 tags. It's not parsing the HTML because the content type is explicitly set to this text plain. Now there might be cases where you want to change the status, right? If you want to send back like a not found page, you could change it to like a 404. So we can do that. Let's go, actually let's put it back to HTML. And then here let's say res.status, or I'm sorry, status code. And we're going to set that equal to 404. And then maybe you'd say like not found or something like that. But let's just... Stop the server reload it and come back here Reload the page and now down here notice that it's red the local host and it has a status of 404 And we could actually shorten this up right so we could do this instead of Separating instead of having two separate lines here. We can use the right head method so we can say right head And you can see here it sends a response header to the request, the status code. So it allows you to send the status code and things like the content type, so headers. So let's wrap in here. Let's say we want to send, let's do a 500. And then we'll set the content type. So here we can have an object with different header values. So we'll say content-type. And we'll set that to application slash JSON. And then we can actually send JSON data here. So let's say JSON.stringify. And I'm going to talk more about APIs and JSON data. But just to show you, put an object in here. We'll say message server error and restart. Okay, so now if I reload this page, now we get this JSON message server error, and you can see it's a 500. Now, before we move further with our server and writing some more code in here, I want to just talk about NPM scripts and NPM modules because I want to install one called NodeMon because it's kind of a pain in the ass to keep restarting the server. So let's create a script first. to run this because right now we're running node and then the name of the file but if we go to our package.json we can add a script in here called start we can replace the test that's fine we're not using that and then let's have that run node server or server.js so now we can do is come down here and we can now run npm start and that will do the same thing okay so that'll start our server now if you If you use something else other than start or test, like let's say we use dev, then you actually have to do npm run dev, not just npm dev. So keep that in mind. And dev is really common because a lot of times you'll have your development environment and then you'll have your production environment. So we'll just put that back to start for now. So next thing I want to do is install nodemon. And when you install something using npm, right, so let me just clear this up. So if you do npm install nodemon, I'm not going to run this just yet, but what it's going to do is it's going to install it from the npm registry or npm js registry. So you can actually go to the website if you want. So right here and search for NodeMon or any package and this will show you the page. You can see the install. You can also use just I to install and then the repository. So you have the GitHub, the home page. It shows you the weekly downloads, version, license, all that stuff along with the documentation. So all the usage. So these pages are very, very helpful and they usually have kind of the same stuff on the GitHub page as well. As you can see, it's like the same exact docs. So I want to install this because I don't want to keep restarting the server, but I do want to install it as a dev dependency, which are dependencies that are not needed for your production environment. So to do that, you just need to add the dash uppercase D flag. I'm just going to close up the package.json because it's actually going to update. So let's run this, npm install, or you could even do just npm i. dash D node mon. Okay, so what that's going to do is a couple things, it's going to create a node modules folder, since we didn't have one, because we haven't installed any packages. But as soon as you install a package, it creates this folder. And if you look in it, there's a crap load of stuff here. And even though we only installed node mon, that particular package, just like every package has a bunch of dependencies. And then those dependencies have dependencies. And that's why you get this big node modules folder. Alright, the other thing it did is in the package.json, you can see now we have this dev dependencies object with the nodemon and the version. Okay, so if we installed it without the dash D, just a regular dependency, then it would be in the dependencies object. So you might, you're going to have a dependencies object if you install something normally. And then another thing that happened is this package dash lock. dot JSON file was created. And this has the entire dependency tree with all versions and everything. You don't have to do anything with this file. All right. Now, when you when you push your code to GitHub, you never want to push the node modules folder. Okay, you don't want to ship this ever, because you can easily just reproduce it. In fact, I'm going to just delete it. And Since my package dot JSON has my dependencies in it, which right now is just one dev dependency of node mon Since I have that I can simply run NPM install with nothing else It's gonna look at my package dot JSON dependencies and install those right so when someone gets your code from github All they have to do is run NPM install and it looks at the package dot JSON Manifest and then it will install the node modules on their machine. Okay, so hopefully that makes sense Now to prevent that from going to your git repository, you can create what's called a.gitignore file. So we can create a new file called.gitignore, don't forget the dot, and then in that we can just simply put node underscore modules and save it, and that's it. Now when we push this to GitHub, that node modules folder won't get pushed. All right, so let's see. The next thing I want to do is use nodemon. And, I mean, you can check the documentation to look at the specifics, but basically all we have to do is instead of node here in our script, we can run nodemon and then the file name. So now if we come down here and I run npm start, it's going to run our server on port 8000 just like it has been, but now it's going to constantly watch it. All right, so if I come back here, So we have our 500 status and our JSON, but let's change it to, let's change it back to 200. Let's change the content type to text slash HTML, and then let's get rid of the JSON stringify and all that stuff. And we can put back H1, hello world. Now normally I would have to restart the server, but if I save, you'll see this kind of refreshes. and I can come back here and reload and it works. Now I don't have to go back and keep refreshing. So NodeMon is just one of those tools that I use in just about every Node.js project. Now another thing that I want to show you real quick is the use of a.env file. So environment variables are variables that are... in your environment on your system and you can access them from your entire program you can access them from different programming languages is usually a certain way to do it with node.js we have the process object and on that is a an env object with all your environment variables well you can create a dot env file and create environment variables in that file and you used to have to install a package called dot env but now with a recent version of node.js you don't have to do that anymore it's you can just do it without installing anything so just to show you let's create a dot env and you don't usually want to push this you don't want to include this in your git repository because a lot of times you'll have api keys like maybe you'll have a google api key you know you'll have something here and you don't want other people to access that or to see that so what i would do is add that to your dot git ignore So we would just do this and then that won't be added to your git repository. So in the.env, let's create a port variable here. So if we want to change the port number, we can just do it from this file. So I'm going to set it to just to test things out. I'll set it to 8080. And then what we can do is go into our package.json because you do actually have to run it with a flag, at least for now. So that would be... Right here where we run nodemon, we can just do dash dash env dash file and then say equals and then the name of the file which is dot env. So now when we run npm start, it'll run this command and it should use that file. So I'm going to save that and then let's go to our server.js and instead of hardcoding 8000 here, we should be able to access it with process dot env. And then anything I put after this ENV dot, I can access any variables in this file or on my system. So let's say port. And now, let's see, I think we have to manually restart the server. Yep, so now you can see server running on port 8080. So it's looking in this file. And I could access process.env port in any file in my project. Now I'm going to put that back to 8000 and just restart the server. And now it's back to 8000, but now it's reading it from here. And again, you would put your API keys, things that you want hidden and you don't want in your source, you know, in your repository. Now, another thing that I want to look at is the request object here. We used a bunch of methods that are on this response object. But there's a bunch of stuff we can get from here. So let's do a console log of, I want to do request.url, and I want to do console log request.method, because those are two very important things that you're going to need in order to respond correctly. So let's go to the browser and just reload. And then if we look in the console here, you can see we have a slash. So that's going to be the URL. because we just went to localhost 8000 and no page after that. And then it's a get request. If you go to a page on a website, that's always going to be a get request. You can submit forms as a post request, or you could make put requests and delete requests either from JavaScript using the Fetch API or from Curl or from a client like Postman, which I'm going to get into. So if I were to go to localhost 8000 slash about, It's going to show me the same exact thing because we're not checking the URL. All right. If we look down here now, request.url is going to show slash about. But we're still giving the same thing. We're still doing this no matter what method we use and no matter which URL we hit. So that's why express is so valuable because you can just do something like this. You can say app.post. So it'll... You can do like app.post, so it'll only be for post requests, and then you can do like slash whatever users. So that will handle, then you'd have a callback here, and then whatever you put in this function, whatever you put in this function would only run if you made a post request to slash users. Now with just the core, HTTP module, we have to manually check everything the URL and the method I'm going to show you how to do that. But just know that this stuff is a lot easier with express. But again, for like the fifth time, I think that it's good to know how this stuff works under the hood. So let's see what should we do next let's make some other types of requests and I would suggest using postman That's the client that I use but there's all types of clients You could just use curl if you want which is a command line utility you could use like file What are some of the other ones there's there's a bunch of extensions for for vs code I actually have the postman extension installed. So if I click on this little icon here, I got to sign in Let's see, this is my workspace. So I would suggest if you don't have a Postman account, I mean, you can just sign in with Google. I'd suggest doing that because this is really helpful. I can just say new HTTP request and it'll open up a window here. And now I can make a request to, let's do 8,000 and I'll make a post request. So I'll click post and then send and you'll see down here in my console, We made a request to slash, which is just the root, and it's a post request. And this is how, if you're creating APIs, this is how you would test your routes without having any kind of front end where you would have the fetch API or Axios or something like that. Routing is also easy with a framework. So let's create just a very simple router. So I'm gonna get rid of this. And you can console log the entire request object if you wanna see some of the stuff that's on there. I mean, you can get headers that are sent. If you have cookies, you can access cookies and all types of things. So I'm going to get rid of this as well. And let's just have like a, we'll just create a little router. So we're going to check the URL. So let's say if request.url, if that is equal to just slash, it's not dot slash, just slash. So that's the route. Then let's... let's see we'll just move this up here i guess we'll move both of these up here and let's say instead of hello world let's say home page and this could be json if you're building an api this could be content type application json you could serve you know json objects or arrays but i'm going to just pretend that this is an html server and then let's say else if and then we'll check request.url And we'll do an API after. We'll do some JSON stuff after. So let's say if it's about, then let's see, we'll copy this stuff here, put that in there, and let's do instead of home page, we'll say about. And then let's say else. So any other page then we want it to be not found. So I'll paste this in and we'll do a 404 and we'll say not found. All right, so this is a very simple, but it is a router. So now we'll save that. Let's go to, I'm going to do it from Postman, but you can do it from the browser if you want. So right now it doesn't matter what method we use. It's just looking at the URL. So if we go to the home page. You'll see we get an h1 and it should be type html right here so content type text html so that's the home page now if I go to slash about that shows the h1 with about and if I go to anything else then I get a 404 not found and we write to the body not found so that's a very simple router now let's let's create a server that will check for get requests as well Right, because if I make a post to the root, I still see the home page and I don't want that. I only want it to be for get requests. So we can go back into our code here. And what we can do, let's do a try catch. And in the try, let's check if get or if get request. So we'll say if the request dot method. is equal to get then we'll do something else then we can throw an error so we have this error object that we can use actually want to do new error it's a constructor and we'll say method not allowed and then I'll just grab this right here We'll cut that and then we'll put that in here. So it has to be a get request. Now if there's some other type of error going on, then let's do a 500. So we can take... This put that there set that to a 500 which is a server error and let's say Server error okay, and you probably just send this like as plain text So we'll do that We'll send it as text plain Okay, so now if I were to make a get request, it should work, but if I make a post request, I get a server error of 500. Now, what about loading files? Instead of, obviously, you know, you're not going to just put your HTML in. inside of this res.end, so we can use the FS, or the file system module, which I do wanna go over more in depth a little later, but let's just use it to now just to load an HTML file. So what we can do is. is have in our structure here, our crazy structure, because this is just like a sandbox. We're not really building something specific. Let's create a folder called public. And we'll say we'll have an index.html in there. we'll have a whoops we'll have a about dot HTML and then we'll have that's it we'll just have those two and then I'll just put a boilerplate in here just say home page home page and then for the about we'll do the same thing Okay, so we have our two HTML files. Now I'm going to bring in up here, I want to import the FS module. And there's multiple ways to use the FS module and to use the methods on it, like read file, write file. file. So there's one way, which is the default, which is an asynchronous callback. And then there's also a synchronous version of all the methods, which does, it's blocking, so it stops the execution of your program until it finishes, which you usually don't want. want to use. And then there's also a promise version where you can use promises either with dot then or with a sync await. So I'm going to import the promise version. So I'm going to say from FS slash promises. And then let's come down here and I need to get the current file path. Now, if you're using common JS modules, the require syntax that we looked at, then you actually have, I'll go right here, you actually have, let's say get current path, some variables, you have one called double underscore file name, which will give you the current file name with the path. And then you have double underscore dir name, which will give you the current path of the file that you're in. So these aren't available if you're using ES modules, unfortunately. They're not available in the environment, and you'll get an error if you try to use them. But we can kind of make our own by using a couple things. So one is the URL. module so I'm going to import URL from URL and these are all these are all core node.js modules you don't have to install these or anything and then let's create our own double underscore file name and set that to URL and then there's a method called file URL to path and in that we're going to use this import import.meta.url which will give us the file URL to whatever this file is in and want the actual file URL, we just want the path. And that's what this does is it takes that file URL, turns it into a path, then what we can do to get the directory name is use the path module. And I'm going to go over these modules more after we're done with the HTTP stuff. So let's import path from path. And this just gives you a bunch of utilities to work with file paths. And on that, we have a method called der name. I mean, I know we're calling this dirname, but this is a variable. This is a method that we can use to get the directory name that we're in, and we just want to pass in the current file name, which we just created here. So just to kind of give you an idea of what this gives us, let's console log both file name and dirname just to see what that gives us. So you'll see right here, the first one, which is file name, gives me the server.js and the entire path. The dir name gives me just the entire path, but not the file name. And these are very helpful, and you'll use these for a lot of different things in your project. So now what I want to do... Is like I said instead of just writing this h1 I want to load a file and instead of kind of repeating ourselves here because we're doing right head and We're actually gonna get rid of these so inside this these conditionals and let's set a file path Variable with let so we'll say let actually let's put this above where we check the URL so above the Above that, let's say let file path. And then in this first if, we want to set the file path equal. Now, we could just do double underscore dir name slash public slash index HTML, because that's what I want to load. But the path module has a method called join, which will just take in arguments. And each argument you pass in is going to be part of the file path. So for instance, I want to take the current directory that we're in. Then I want to go into the public folder, and then I want to go into index.html, or load index.html. All right, and then I'm going to copy this line and then go into here, and instead of index.html, we want this one to be about.html. And then if it's not found, I mean, we could create a not found page or whatever, but I'm just going to do a throw. We'll say throw new error and just say not found. All right, now since we have that file path variable, let's go under the if statement, still within the if get, and let's say const data and set that to await. And we do have to make this asynchronous. So up here, just put in async. And I'm going to be using the read file method on the FS module. So we're going to await fs. Read file and then pass in that file path. Okay, and then we'll go ahead and let's set the content type to HTML. So we'll say res.setheader. And let's do content-type. And let's set that to text slash HTML. And then we'll use res. We'll do res.write. and pass in data, which is going to be the file, and then res.end. All right, so that should work. Let's save it, and now I'll do this from the browser. So let's go to localhost 8000 about. I reload, and now it's showing me the HTML, the about.html. You can see the title says about. So anything I put in that HTML page is going to show here. If I go to just localhost 8000, then it loads the home page. If I go to slash test, which doesn't exist, then I get a server error. Probably better to put a 404 not found page, but I don't know. I guess that's fine for now. You guys get the idea. And again, sixth time I've said this, you're not going to be doing things like this in your actual projects. If you use Express, this is a lot easier. This is just very low level. It's a web server. You could build your website and start to put your HTML together, your CSS, and all that. Now I want to show you the other side of building an API, which is very common. A lot of times you'll have your back end will be a JSON API, and then you'll have React or Vue or something on your front end, and you'll make requests using the Fetch API or using Axios. You'll make requests to the back end to get your data, and your back end is where you'll interact with your database or whatever it is you're doing, GraphQL, anything you want really. So let's um I want to keep this code here So I'm going to close it and I'm going to create another file called server 2.js And I want this file to run when we run npm start So let's go into package dot JSON and just add a 2 onto this server Js so now if I restart this and I run it it's running, but there's nothing in our in our code So I'm just going to stop it for now, so let's once again. We're going to use the 8 the create server method from from the HTTP module. But since that's the only thing we're using, we can actually just import that. I'm sorry, we want to use import. And we can say import, create server from HTTP. Okay, because that's, that's all we're using. And then let's just create some users. So this will be a users API. And again, this would probably come from a database, but we're just going to hard code just an ID. we'll do an id and a name so john doe copy that down we'll do Jane Doe ID two ID three. This will be Jim Doe. All right, so we have our users. Now let's do the same thing server set that to now we can just say create server, we don't have to put the HTTP in front of it. And that takes in a function with request response. And then down here, we want to just listen. So server Dot listen actually just just grab this So we'll do that and let's just add our port up here. So cons port that's going to be from our environment. So process dot e and v dot port Okay now in here, let's check We want to check for the URL, and we want to check for the method. Because with an API, usually you're going to listen for, like, post requests to add a user, get to get the users, put to update, and delete to delete. Now, I do have a video. on my channel. It's called something like build a REST API with Vanilla Node.js, and that goes much deeper than we're going to do here. I just want to be able to get users and get a single user. But again, if you want, I'll put that video in the description if you want to take this further. So let's say if the request URL is equal to, and we have something like API slash users, and let's check for request dot. method and see if that's equal to get. So if that is, then let's do res.setHeader and we want to set our content type and for JSON it's going to be application slash JSON. And then let's do res.write. And in here we're going to do json.stringify. And again with express you can just pass in, you can do something like this. Don't type this but you can do res.json and you can put your javascript object right in there and it will just parse it as. json you don't have to do json stringify so let's pass our users in there and then we just want to end the response and that should work we can make should be able to make a request now well let's run our script and then make a request to slash api slash users and there we go so we get a 200 ok and check it out we have our users down here in the body Now let's make it so if we hit a route that is not this, that doesn't exist, then we'll just say, you know, route not found. So let's have an else. And for this, let's do, let's see, I'll just copy this. Then I'm gonna just put in a message here. Let's say message route Not found so if we do that and then Let's go back here and let's go to just api i don't know to do's and we get route not found now you should probably make this a 404 so what we could do is just go in here and say res dot status code and set that equal to 404. And now if I make that again, now I get route not found, but my status is a 404. So you want to follow these conventions when building an API. Now let's say we want to be able to go to like slash users slash and then the ID of the user, or it would be, sorry, API slash users and then the ID. So I want to be able to do that. So we can put another basically put another route in here so we'll say else if i think that yeah so we'll do that is that right no we need we need our curly brace here as well all right so else if now this is difficult using just node and the hdp module if we're using express we could just have a route where we're saying if it matches, you know, API, we could do like if it matches API URL, and then colon ID, which would be dynamic this ID, then you know, do whatever. But in this case, one way to do it is to use a regular expression and use the match method so we have our url so request.url and then we want to say if it matches and then the regular expression i'm just going to grab that and throw it in i hate typing regular expressions out so it's going to be wrapped in these double forward slashes. And what this is saying is it needs to match slash API, literally slash API, and then slash users, and then slash any number. Okay, so this is brackets zero through nine. And we also want to make sure it's a get request. So let's say and request.method is equal to get. So if that's true, then... For now, let's just let's just copy this just to make sure that that works. And I'll just for now just pretend this is a user. So name John dope. OK, so let's try that and just see if that comes up. So we'll send and there we go. All right. Now to get the actual user by its ID. We can see. I'm going to go right above that and let's say const ID because we need to get the ID from the URL. So what we could do is say request.URL and we could use split. And we want to split it on the slashes. And then it should be the third one. And just to test that out, we could do a console log of the ID. And now if I go and I hit that route, down here you can see one. If I pass in right here to send it. Now we see two. So we got the ID. Now we want to get the user. So let's say const user and set that to users.find. And find is just a JavaScript method. Takes in a callback. So it's going to look for the user. And once we get that user, we want to return if the user.id, right? So this loops through the users. We're saying for each user we want to. to check the id and see if that's equal to the id variable but let's parse it as an integer so parse int or parse it as a number okay now we'll come down here and we'll say if user so if that user exists then let's go ahead and cut that so if the user exists we'll go ahead and put in here in this json stringify that user variable and then else so if that user does not exist then let's do this and let's say user not found because it is a it's a route but the user's not there so we'll try that out let's go to postman or your browser whatever you're using i'm going to send and you'll see it gets me the user with the i ID of 2, that gets me the user with the ID of 1. If I do 100, user not found 404. So this is the beginning of a REST API. And again, it's very kind of messy code. It's confusing. That's because it's just the HTTP module and normally you're going to use a framework. If that's not clear by now. And we could actually, since we're using this twice here, we could actually get rid of these and put this, put that here and then get rid of that because we're doing that either way. And same thing with res.end. We could. Go ahead and put that down here, res.end. And let's make sure that that still works. So user not found. Users gives me all of them, slash one. All right, cool. Now let's talk a little bit about middleware. So middleware are basically... modules or functions that have access to the request and response object because they sit in the middle of incoming requests and outgoing responses and they can perform basically any code that you want, you can execute any code, you can also make changes to the request and response objects. All right, so if you wanted to add a value onto these, you could do that. A lot of times when you have authentication middleware, you'll end up with res.user and you'll have access to the logged in user. And then you have to call the next middleware function with the next function. So to give you an example, let's add to this, I'm going to create a middleware function and usually you'd put this like in a separate file but I'm just going to put it here let's say we want some logger middleware that will just will log the the url and the method whenever a request is made so let's create a function We'll call it logger. Now middleware is going to take in request, response, and next. And this is the same whether you're doing it with just Node.js or with Express. So let's do a console log and put some backticks in here. And I want to log the method. So remember, we have access to request, so we have access to request.method. And then next to that, let's do the request.url. Now, since this is middleware, we have to then call the next function because that basically says, okay, this is done. Let's move on to the next middleware. Now to use this, we actually have to wrap, we have to run it and then everything we're doing here, we have to wrap in the callback. So let's go into the server. I'm going to clean this up after as well, but let's go ahead and say logger. And this is going to take in request response and then a function. And in that function is where I basically want to have all this. So I'm going to grab from here down to here, cut it, and then put it in here. OK, so now let's make a request. So we'll do the get to this this users one. And now notice down here in the console, it says get and then API users one. If I do API users, if I do a post request, which shouldn't work, but it still shows it down here because we're logging the URL in the method. So that's an example of middleware. Now, I want to clean this up a little bit and we could actually. Since we're doing the application JSON Basically everywhere so you can see it. We're kind of repeating ourselves. We could make that a middleware function. Let's say JSON middleware so say const JSON Middleware and set that to that's going to take in requests response next And all I want to do here is this. So I'm going to take that, put that there, and then we can call next. So that's all I want that to do. And then for the user stuff, right? So for here, for this route, where is it? Yeah, for this route, API users, we're getting all the users. We're sending all the users. For this one. We're sending back an individual user. So let's create a handler function for those just to clean it up. So we'll say route handler for slash API slash users. Actually, we'll say for get API users. So const get users handler, and we'll set that. equal to now this is not a middleware function it's just a handler it's just a function and takes in request and response and we're going to just do let's see this right here and the end because we don't have to do this that's going to be taken care of with with the the middleware all right so that's the get users handler now let's do the get the user by id so say route Handler for get slash API users slash and then the ID. So we'll call this get user by ID handler. All right. And then what I'll do is grab, let's see. We want the ID, want this, these two lines, the ID and the user. So we'll put those in there. And then we want to check for the user. So we'll grab this if statement right here, and the end, grab that. Put that in here. So you can see it's just breaking it up and it's making it cleaner, it's easier to read than this slop that we have down here. And then finally we could have a not found handler. So let's say not found. So const. Not found handler and set that quest response And for that, let's see, we'll grab the 404. We'll grab this and the res.end. Put that in there. Now we just have to put it all together. So we have our logger. I'm just going to get rid of everything in the logger middleware. I'm sorry, in the logger callback. So all this stuff. And since we have two middlewares, we have logger and we have the JSON middleware, we can basically just kind of stack them in here. So JSON middleware, request, res, and then the callback. And then that's where we want to do our routing, so we'll check if the request.URL is equal to slash API users, and the request.Method is equal to get, then we want to call the get users handler. Okay, so this is much neater else if Now this is where we have to do our little Expression so request dot URL dot and then we'll use match And let me just grab that Expression same one we had so that and we want to check to see if the request dot, see if the method is equal to get. If that's true, then we want to call our get user by d handler, right? And then else. then we want our not found handler. Oh, and we have to pass in request response into those because it's not going to know what those are. So make sure in these handlers, pass these in. Okay, so let's try it out. So I'm going to go API users, and we get all of our users. If I do slash 1, if I do slash 11, we get not found. If I do API use, which doesn't exist. I get route not found and we're out logging middleware is also working now. What if we took this a step further and Made it so if we make a post request we can actually send data and create a new user I think that'll give you a good idea of how to act get data from the body of a request. So let's add a new handler. So this is much more scalable now because now I can just create a route handler to a right route handler for a post request to slash API slash users and even though this route was already used with a get request it's fine because it's going to be a different method. So we'll say const create user handler and it's going to take in the request response and getting body data is much more difficult i mean it's not difficult but it's it's more difficult than with express because with express you would send your body data you know send your json and then you could just access it with request dot body and that would give you the the name the whatever it is you're sending here it's a little different so first thing we're going to just create a variable called body and set it to an empty string and then what we do is we listen for the data By doing request.on. So we're listening for a specific event here, and the event is called data. And when that happens, we have this callback, which takes in a chunk. Okay, so this... chunk, we basically have to take, we're going to take our body variable and we're going to append onto it that chunk, but we want to make it a string. So we want to convert it to a string. And that should give us the data. And then underneath that request.on, we're going to do another request.on. And now we're going to listen for end. And when that happens, we'll have a function. And we should have access to that body variable, which will include whatever we send. So let's say const new user and set that equal to, and we're just going to parse it. So json.parse, parse that body. Because it comes in as json, but we want to turn it into a regular JavaScript object. And then we'll take our users array and we'll push on to it. In reality, you'd be adding it to the database, but we're just... Adding it in memory here onto the users array. And then we'll do a res.status code of 201, which means successful and something was created. And then we'll do a res.write. And let's send JSON. So we're going to stringify, which is the opposite of JSON parse. Here we're turning JSON to a JavaScript object. Here we're turning a JavaScript object into JSON. Send the new user and then res.end. Now let's come down to our router. Okay, this is our router basically. It'd probably be better as a switch, but this is fine. So I'm going to add another else if. So right here before the else, let's say else if. And then so we want to do that. And we'll say if the request.url is equal to. And we want to see if it's equal to API slash users, but we want to make sure it's a post request. So we'll say and the request dot method is equal to post. And if that's true, then we want to call the create user handler and pass in the request and response objects. So let's try it out. We'll go to Postman and we're going to select here body and then raw. And we're gonna send the ID. Usually you wouldn't send the ID. You'd have the database would create it on its own or recreate it on the server side, but we're just gonna send it for the, just to keep this simple. So ID, we'll set that to four, two, three, four, whatever. And then for the, what else do we have? The name, we'll set that to, just say Brad. So I'm sending a post request, so I wanna select post. and I'm sending this in the body. So let's send and we get route not found because this needs to be API users and there we go. So we get a 201 created and we get back the new user and if I do a get request now to API users you can see that Brad is now included. Now it's just in memory. If I reload then that's going to go away but you can see that it's working how it's supposed to. So I think that that's going to be it for the HTTP method. We did quite a bit, but I want to move on to some of the other core modules. Like, I mean, I know we use the FS and the path module a little bit in our API and stuff, but I want to just get a little bit deeper into those. So let's close these up. And I'm going to stop the server because we're actually going to be using different files now. And the first module that I want to look at is the FS or file system module that we did. We looked at a tiny bit, but I want to give you a better idea of how that works. So let's create a file. We'll call this fsdemo.js. That'll be the convention when we look at these modules is just whatever it's called and then demo. So let's import FS from FS. And if you go to the Node.js documentation, All the core modules you can find on the side here. So file system, if you take a look, there's tons of methods. So read file, sync, truncate, write file, all kinds of stuff. Then you have to deal with permissions and pretty much anything you want. Creating directories. I'm definitely not going to go through, you know, all of these or even a lot of them. I'm just going to show you probably write file, read file and append file. just so you know how they work because there's actually multiple versions of some of these. You can see that like this one right here, chmod sync, and there's a chmod. So chmod would be the asynchronous version which is non-blocking and then chmod sync is the synchronous version which will block and it will wait for that method to finish until you know for it to continue executing your code. Which in most cases you want to use the asynchronous version, but you know that there is a synchronous version available so we'll start with the read file method and i'm going to show you the different versions so we'll say read file and this is the it's the async version but it's the callback version because there is a callback and there is a promise version callback is kind of the default so Let's yeah, we'll just do this so let's take FS and we're gonna call read file and read file does just that It could be a text file. So let's create we'll say test dot txt and I'll say this is From the text file, so I want to read what's in this file into my program So this is going to take in three things first is going to be the file location, which is in the same directory test dot txt and then the second is the the encoding which is going to be utf-8 and then third is the callback so this is asynchronous so this callback will run once that the file is read so this takes in a possible error and then the data from the file and then we could just check for an error if there is then throw error and then let's just do a console log of the data in the file So now I want to run this fsdemo.js, so I'm just going to say node fsdemo.js, and we see this is from the text file. So that's the first version. Now I want to show you the synchronous version, and this is actually called read file sync. Okay, so this is the synchronous version. Now this is written easier, in my opinion, but... It's blocking, so if it's a giant file that you're reading, it's going to stop the rest of your code. So you usually want to use the asynchronous version. But if it's something really quick and it's not going to affect performance, you could just use this. So read file sync takes in the location and the file name, so test.txt, and then the encoding, and then we can just console log that data. So now if I run FSDemo. You can see that it runs twice. First for this, the asynchronous, and then once for the synchronous. Now I want to show you the promise version and there's actually a separate import for that. So we can import, let's comment this one out and say import fs from and then it's going to be fs slash promises. And then I'm just going to comment out these so we don't get any conflicts. And let's say this is going to be the read file. And this is going to be the promise version. And there's basically two versions of this because we can use the.then syntax. And we can use async await. Now out of those four, async await is my preferred. So that's what we'll use for the rest of these. But just to show you, we can say read file and then pass in.slash test.txt. Pass in the encoding. And then take off that semicolon and we can add dot then because remember this returns a promise So dot then and then we have our function with the data Console dot log data and then we can add a dot catch for errors So that'll take in a function with error Okay, so now if I run the file we should we should see this is the text from the file and we're using the promise version So let's do the the async await Example so say read file and this is gonna be a sync Wait, I'm just gonna comment out this one Now with async await, obviously we have to wrap this in an async function, so let's create a read file function, and it's going to be asynchronous. And then in here we'll do a try catch to handle any errors. Okay, and we can write it just like we can do the sync version. That's why a sync await was created, so we can write code that looks more like this than like this. Right, in fact, I could just take that and instead of calling read... file sync we'll call read file and we just have to put a weight in front of it and then we can console log the data so this is my favorite way of doing things because it's more readable and it's asynchronous and then here we'll just console log error and then we have of course we have to run read file And there we go. So we get this is from the text file. So those are the four different ways to use this function or to use really any of these FS methods. So the next one we're going to look at is write file. So let's say write file. And I'm not going to do it four different times. I'm going to use the async await version. So let's say const write file. And it does just that. It writes to a file. If it doesn't exist, then... it'll create it so let's say async and again we'll do try catch and in here we're gonna we don't need to return anything from it so we'll just simply say await and then write file it's going to take in the location and name of the file i'll just use the same one we don't need to put the encoding what we do need is what we want to write to it so let's say hello I am writing to this file. And then we'll just do a console log and we'll say file written to. Okay, so now let's do the write file before the read file. So we'll go ahead and run this and now we see file written to and we see hello I'm writing to this file and if I open up that test dot txt you can see that it it overwrote What was there so it's always going to overwrite whatever you have there now if you want to add something to it and not overwrite It you can append so that's where append file comes in so for this let's say const append file Okay, and then we'll do... We don't have to return anything, so we'll just say await fs.appendfile, and it's going to take in the file we want to append to and what we want to append. So I'm going to put in a string. I'm going to use a new line character, which is slash n, and we'll say this is appended text. And then I'll just console.log, we'll say file appended to. Alright, and then we'll call this, let's do it second, so append file, and then we'll read it. So we'll run, file written to, file appended to, we see the first line, and then we see the appended text. And if I look in the file, on a new line, we have this. This is appended text. So that's kind of the gist of the FS module. You can do all types of stuff with files. If you want to save logs or whatever, you could even integrate it into our API, into the logger middleware to log it to the file. In fact, that could be a little assignment for you guys to do. So the next thing I want to look at is the path module, which we looked at a little bit. So let's create path demo dot JS and we're going to bring in path from path. Okay, now, and this is, it gives you utilities to work with file paths. And it doesn't matter if the file path is there, if like it's actually in our structure or not. So I'm just going to create a variable to represent a file path to work. with. So we'll do dot slash dir one slash dir two slash test dot txt. Okay, that's not a real location. But that's what we'll use to kind of show you the different utilities we have. So the first is base name, all lowercase, and this will return the last portion of a path. So we can simply console.log path.basename and then pass in our file path, and then we'll run this. So remember, you've got to run path demo.js, and we get test.txt because it's looking at this, and it's just giving us the file name, just the base name. Now we can do the opposite and get the directory with dir name. So dirname and let's do console log path dot dirname and then file path and take a look and you can see here it's just giving us the the file path the dir dir 1 dir 2. Now you might want to get just the extension name so ext name will do that so we'll go ahead and console log path dot ext name and then pass in our file path and when we run that we should see dot txt. Because it's just going to give you the extension. Now there's also a method called parse that will basically give us an object with all this stuff right here. So if we console.log path.parse And we run that. So we have an object with the root, which is just an empty string, and then the dir, or the directory, the base, the extension and name, just the name of the file. So there's going to be different cases when you're working with file paths that you're going to need stuff like this. Now I already kind of showed you how to get the dir name and the directory name and file name of the current file, but I'll just go through that again and again if you're using common js you have access to double underscore dir name and double underscore file name you don't have to do anything but if you're using es modules you have to kind of create it yourself and we do that by using again the url module And then we can use the, right here, so filename equals URL and then the file URL to path. And what we pass in here is the file URL, which we can get from import.meta.url. Okay, so that import meta, that gives us something like this, file, colon, slash, slash, and then the file path. But we want just the path and not that file, colon, slash. So this will give us the... the actual file url i'm sorry file path and then to get the directory name we can just do der name and set that to and then use the path module and the der name method and then pass in double underscore file name and you have to bring in path and it auto imported for me that's another thing too if you use sometimes if you use something in bs code a module and you don't import it, it'll auto-import it for you. And then you can console log both of these, so we get the file name, we get the path name, sorry, the dir name, if I run that. So here we go, this one has the actual file in it, this one is just the path. Now another one is join, and I believe we used that already as well. And what join does is it will create a file path based on arguments passed in. The main reason for this is because on different operating systems, you have different delimiters. So for instance, on Linux and on Mac, you would have a path like users forward slash Brad, right? But on Windows, it would be users backslash Brad. So what join does is you just pass these in as arguments, and it'll automatically put the correct delimiter in. So let's... Let's try that. We'll say const and let's say file path 2 and we'll set this to path.join and we'll take the current directory name and then we'll add on to it, let's say dir1 and dir2 and then let's say test.txt. And then if we console.log file path 2. And we take a look. It's going to be the current directory that we're in, which is, for me, is going to be this. And then we added dir1, then dir2, and then test.txt. So it just joins and constructs a path. Then we also have resolve, which will basically do the same thing, except it's always going to be an absolute path. In fact, you can use these kind of interchangeably. I can actually just do this. We'll change that to 3, and then we'll here, instead of join, we'll use resolve and we also want to log file path three and if i do that you'll see we get the same exact thing all right and there's tons more methods you can check out and you can look at the documentation for that but i do want to move on so the next one we're going to look at is the os module so let's say osdemo.js and we're going to bring this in so import os from OS and this will just give you information about your system Which is nice if you want to create something that interacts with the memory on your system or the CPUs or something like that Maybe you want to create a little visualization for For the memory used things like that. So the first method that we're going to look at is user info Actually, it's a capital I And that will do just that. It'll give you information on the current system user. So let's do a console.log os.userinfo. And then, of course, we're going to run the OS demo.js. And this is what it gives me, an object with the UID, GID, username. Obviously, yours is going to be different depending on your system and your user. Of course, if you wanted just the username, you could just add on to this.username. And if I run that, it gives me my user, which is Brad Traversy. All right, so next we're going to look at some methods that have to do with memory. So we can get the total mem. Actually, it's all lowercase, this one. So total mem. And let's console.log os.totalmem. And we'll run that. And that's going to be in bytes. So this is the total mem. And then we also have free mem. which will be the free memory, so os.freemem. run that i forgot my parentheses okay so we have the total memory and we have the free memory now if you want information on the cpus there's a method called cpus so we'll console.log let's say os.cpus And what this is going to give you is an array, and then you're going to have an object for every core on your system. So you can see I have Intel Xeon, and it's going to give me an object for every core on my system. system. I think that's good for the OS. There are some other things, but you can check out the documentation for those. Now we'll jump into the URL module. So let's say urldemo.js. And we'll import URL from URL. OK, so I'm going to just construct a URL string to work with. So let's say url string. And we'll set this to, I want to have something that has a query param in it as well. So we'll use like a Google search. So we'll say www.google.com slash search. And then we'll add in a queue param, so a search query. And we'll set that to hello plus world. Okay, so if you were to search hello world on Google, you would have a URL like this. Now I want to construct a URL object to work with. And we can do that. with the URL constructor so let's say const URL OBJ set that to new and then the URL constructor and we'll pass in our URL string and then just to see what that gives us let's console log URL object and basically it's going to give you all kinds of stuff from that URL make sure you run the right file And you can see our object here. It has the href, which is the entire string, the entire link, the origin, which is just the domain, the protocol, username and password if there's one, host, the port if there is one, the path name, which is slash search, the query string here. So you get the whole question mark Q equals hello world. And then you also have a URL search params object with each key and value. and also a hash. So you can access any of these by themselves. So if you want to do like, like dot path name, and there you go, we get slash search. So let's look at some of these other methods. So format. what format will do is it takes the object and turns it back into a string. So let's do a console log of url.format and let's pass in our url object and you'll see that that will just give me that'll just put it back into string form. We talked about the import so import.meta.url so this is kind of a special variable and again it provides the well this provides some metadata about the current module so it's not actually part of the url module but this is useful to know and it gives you the the file let's say the file url so if we were to console log this directly import meta dot url then you can see it gives us the the file it has the file protocol here and then the path and then we already saw this as well the file file url to path which will just convert it to a regular path so we can say console log url dot File URL to path and pass in import meta URL. And now if I run that, now we just get the path. Now, the next thing I want to show you is how we can get the search params or the query params. So, like, for instance, we have a key of Q and a value of hello world. So what we can do... Remember, we can get the URL object dot search. So if I do that, it's going to give me the entire thing, the Q equals hello world. But I can go ahead and say const. and I'll create a params object with new and then URL search params and pass in the URL.obj and then.search. Okay so I'm passing this into this. And, yeah, let's go ahead and console.log now params. And that should give me an object. Yep, so we have an object with Q, and then the value is hello world. And, of course, if I wanted just the value, I could actually do this. I could console.log params. We don't do this. Like, you might think we can do params.q. But we don't. We use a get method, and then we pass in q. So now I should just get hello world. Okay, and you can even add on to the params. So, for instance, we can say params. append let's say we want to add on a limit and Say we want to set that to five now if I let's move this Down here and log params and we should have the Q. Hello world, but we also have that limit And you can also delete as well. So I could say params.delete and I want to delete limit. And now if I log params, now limit is gone. And you could also loop through those as well. All right, and there's a bunch of other methods, but I think that we'll go ahead and stop here as far as the URL module. So the next one I want to look at is called crypto. So let's say crypto. CryptoDemo.js. So what this does is it provides cryptographic functionality. And you can read more on the docs, but you can do things like create hashes. So if you want to hash passwords, you can create random hexadecimal strings. You can encrypt and decrypt data, just all types of stuff. Some of this can get really complicated. So I'm just going to do a couple simple things. So let's first import. crypto from crypto and the first thing i want to show you is how to create a hash with the create hash method so let's say const hash set that to crypto dot hash and then what it takes in what it takes in is the algorithm that you want to use, which could be like MD5. I'm going to use SHA-256, which is pretty common. All right, and then to actually hash something, we use the update method. So let's say hash.update, and whatever you want to hash, we'll put in here. So let's say password1234. And then to... get that hash i could use the digest method so hash dot digest and then we want that to be in hex so we'll pass it in hex and whoops we want to run the correct file so node crypto demo js let's see what's going on here the input argument must be an instance of buffer typed array or data view let's see you So, const hash equals crypto dot hash. I'm sorry, this should be the create hash method. all right so if i do that and there we go so there's our hash and you you never want to obviously you never want to store plain text passwords and databases so you could hash it before you put it in now you might want to just generate generate random um i can never say this word cryptographic cryptographically strong um data or a cryptographically strong hexadecimal string and you can use random bytes for that so let's say crypto dot random bytes and you put the size in here we'll say 16 and then you have a callback that can take in an error and a buffer so we'll say buff and then we can check for the error so we'll say if error then throw error and then let's just do a console log of now we can take that buffer and we can use to string on it and let's pass into to string hex So now if we go ahead and run that, you can see it gives me that random string. If I run it again, it's always going to be different. And you can even use this for something like user IDs, things like that. Now, I want to look at, let me just put a comment here, so this is random bytes. I want to look at encrypting and decrypting data, and we can do that by creating ciphertext, which is an encrypted form of a message or data. So basically, It will encrypt plain text, which is readable data, into ciphertext, which is unreadable data, using cryptographic algorithms and keys. And the ciphertext can only be decrypted back into plain text by someone who possesses the correct key. And it also uses something called an IV, which ensures that even if it's the same plain text and it's encrypted multiple times with that same key, the resulting ciphertext will still be different each time. Now I think I should just paste some of this in because it's kind of long. I don't want to type it all out, but I want you guys to know how it works. So we're going to be using two different methods. The first is create cipher IV and actually I think it's lowercase. Yeah, create cipher IV and then create decipher IV. So. we need three things we need the algorithm so in this case we're using the aes-256 cbc algorithm if you go to the docs you can see the different algorithms that are available and then we have our key which is just going to be a random string and passing in 32 and then the iv also just a random string of 16 and then to encrypt or get our ciphertext we can use crypto dot create cipher iv pass in the algorithm key and iv which we're doing right here or creating right here and then we're using the update method just like we did with the hash passing in whatever it is you want to encrypt the encoding type and then hex and then here we're taking that variable and appending onto it cipher dot final so in order to to encrypt that we need to use that final method and then we're logging out the encrypted text so let's see what that gives us we should actually comment out this stuff here okay so if we run that and this is this is now this in cipher text so it's encrypted now to decrypt it we kind of do the same thing except we use create decipher iv pass in the same three things the algorithm key and iv and then we use update again and we pass in the encrypted string And then we can append on to that variable dot final and then log it. And we should see the text. So hello, this is a secret message. Okay, so this is the encrypted or cipher text. This is the plain text. Now there's tons of other things you can do with the crypto module, but I think we're going to stop that here. And the next thing that I want to look at is the events module and the event emitter. So let's create events demo dot JS. And we're going to import. Now, I'm only using one thing from here, and that's going to be the event emitter. So I'm just going to destructure it. So we'll say event emitter, and we're importing that from events. Now, this is great for building real-time applications because you can create custom events, and you can listen for those events. You can also listen for built-in events like the data event on a readable stream. So let's... create an instant an emitter instance so we'll say cons we'll call it my emitter set that to a new event emitter or yeah so that will give us an emitter now i want to create a couple functions that we want to to run or to call when an event is emitted so let's do something just very very simple we'll create a greet handler and we're just going to have that console log Hello world and then let's create a goodbye handler. So we'll call this one goodbye handler and we'll say goodbye world. Now the on method is used to register event listeners and you can listen for multiple events and have multiple listeners for the same event. So let's say register register event listeners so we'll take our emitter so my emitter and then we're going to use the on method so dot on and we'll say on the greet event then I want to call the greet handler these are obviously very very simple examples and then let's have another one called goodbye and for that we'll call the goodbye handler All right, now... Let's emit some events, and we can do that with the emit method. So on my emitter, we have emit, and let's emit the greet event, and then let's emit the... Goodbye event now if I run that file, so let's clear this up. Let's run node Events demo and we see hello world and goodbye world so I mean obviously these are very very simple examples But this allows you to to emit events from anywhere and you can create real-time applications. You can also pass data with the event. So when we emit here, let's say with greet we want to pass in, we'll just pass in John, and here we'll pass in John as well. And then what we can do is up here in the greet handler, we'll say name, and let's... Let's do this. Let's say hello. And then we'll just add on to that name. And then the goodbye handler. And we have access to this this name argument, because we're passing in a second. argument to emit so here let's just say goodbye space name all right so let's run the file and now we get hello John and goodbye John and then to handle errors we can actually listen for the error event so let's do my emitter dot on and on error Then we have a function with an error. And we'll just do a console log and we'll say an error occurred. And yeah, we'll just we'll just also pass in error. And that's going to give us the error message and the stack trace. So now let's simulate the error. we can do that by taking our emitter and then emit error and then we'll say new error and just pass in something went wrong Alright, so now let's run the file and you can see we get this error here, an error occurred, which is coming from right here, and then something went wrong is the message that we passed in to this, to the error. And then we also have the stack trace. I wanted to look at the process module a little bit, or the process object, and it's a global object, so we don't even have to import it. And we've used it a little bit by using process.env to access our environment variable. variables. So let's create a file called process demo dot j s. And like I said, we don't have to actually, I think I said it, we don't have to import it. You can if you want, but we should have access to, I mean if you do console log process and we run node build. Process demo you can see we have access to this and the first thing I wanted to look at is this argv Property which is an array and it has two things in it by default it has the path to node.js and the path to the current file. But if you add arguments in the command line, you can access those from there as well. So if you want to create CLIs, command line interfaces, it's helpful. So let's console log process dot. arg v and let's pass in we're going to run the file but i'm also going to pass in import this could be anything i'm just using import as an example and now what it gives me is the array with those two paths and then the third item in here is import right if i add something else like let's say i want to add a flag like dash s and then i run that now dash s is the next item in the array and if i want to access one of these you know on its own i could do Since it's an array, access the third, and that gives me just.s. And I could say, you know, if this is equal to dash s, then whatever, whatever the logic is for that flag. So it's really cool for command line interfaces. Let me just put a comment here. So this is the argv property. Now, we talked about and we looked at process.env a little bit because we, you know, You know, we set our port in the.env file, and we were able to do process.env.port. But there's a ton of stuff on this. If we just look at process.env and we run this, you'll see you're going to have a whole bunch of stuff from your system. Because this doesn't just have to do with this program or even just Node.js. It's just your system things. For instance, the computer name. I can do process.env.computerName. Pretty sure that that's correct. Or maybe not. I could have swore that was on there. Maybe it's not computer name. Let me see. All right, so let's look at log name, for example. So if we do process.env.logname, so I get Brad Traversy. So you can check out all the system variables you have. Another thing is the ID of the Node.js process, and you can get that with pid. So let's say console.log process. If I run that, you can see that's my node.js process. If you want the current working directory, you can use CWD, so console.log process.cwd, which is a function, sorry. And there we go. So that's my current working directory, you can get the string that represents the title of the node js process. So title. So console log process dot title. If I run that I get just node. memory usage is another one. That's a method. So memory usage. So console log process, memory usage. And we get this object which has all this information in it. You can also get the uptime. Now there's an uptime for the OS module as well. That's your system uptime. This is the uptime of just the process. Now when I do this, process.uptime, it's going to be something very, very short. So 0.03 seconds. because it basically is the time from when you run the command to the script executing, which is obviously a very short amount of time. Now another method you might use is... exit. So basically exit will, it'll exit the process and you can pass in a specific code where zero means success. And if you pass a one in, it's just a general error. So if I do process dot exit and pass in zero, which is just success, like it's supposed to exit. If I do a console log after this, and I say hello from after exit and I run the file you'll see that this this does not get logged because it exits the process Now we can also pro register process event listeners with the on method. So for instance, and I'm going to go above the exit, so it actually runs, we can say like process dot on. And exit is actually an event we can listen for. And then we get the code in this callback. So let's say console log, and then we'll put some backticks. And we'll say about to exit with code. and then we'll pass in the code. Okay, so let's run the file, and we see about to exit with code 0 because this event was fired off when we ran this. All right, now there's still a ton more modules. I mean, there's the debugger modules. There's you can create streams. You can run tests. This could go on and on, but I think that this just gives you a good idea of what you're doing. what is included with Node.js at its core. Like I said a million times, you're going to be using packages. You're going to be using frameworks and libraries. This is just what it offers at kind of a base level. So this was more of just a learning experience, not really practical in how you would actually build projects. So I'm going to start working on my Express crash course. I'm going to revamp that and modernize it a little bit. But that's it for now, guys. Thanks for watching. I do have a Node.js API masterclass course at TraverseMedia.com and on Udemy, where we build a pretty extensive API for coding boot camps. So you might want to check that out. It is a couple years old, but it's all still very relevant. Not much has changed as far as the syntax goes. So you might want to check that out. And I also have that vanilla Node.js REST API video. I think that's a good... good place to go from here as well but either way thanks for watching guys i appreciate it and i will see you next time