Now we wrote our first bit of JavaScript code
that was executed with Node JS,
but of course this code is not too impressive.
We could have executed that same code
in the browser as well.
If we would have added this into a JavaScript file
that is standing colluded in an HTML file
with help of the script element,
basically what we did before.
But of course, the idea now is
that we do write some code that executes
on a server because then, as a next step,
might do useful things for us there
that can't be done in a browser,
like storing user input in a database,
or generate some dynamic HTML code.
I outlined all the reasons for having server-side code
over the last lectures and sections,
and therefore to get there step by step and to get started,
let's now actually write some JavaScript code
that can be executed with Node JS
that will then actually send a response to a browser.
So, that will be responsible for
showing something on the screen.
And for this, we need to use Node JS
and the JavaScript code we execute with it
to build a web server on our own.
Now that's where things can get tricky
to wrap your head around.
We did already host a basic website
on a drag and drop static site host
way earlier in the course.
We used Netlify Drop there, if you'll remember.
Now, there, we used a hosting provider
that created a web server and hosted our files for us.
And during development, we used this
Visual studio code extension to Live Server
to have this other reloading experience
where we also served our HTML files
with that development server,
and under the hood,
that also was a pre-configured server running on our machine
that was accepting requests
and sending back our HTML files as responses.
That is what this extension did under the hood.
Now that we'll write our own so-called server-side code
using that extension
or deploying our page
on a service like Netlify Drop,
which gives us a pre-configured web server,
will no longer be an option
because if we want to execute our own code
that executes on that remote machine,
on that server,
then we also have to write the server itself ourselves.
And that might sound very complex,
but thankfully, Node JS makes that simple.
As a side note, I'm often saying server-side code,
even though over the next minutes,
we'll write our own basic web server with Node JS.
Still, I always mean the code that runs on a remote machine,
which once you deploy your application,
would be exposed to the worldwide web,
and which would handle incoming requests from your visitors.
Now that's what we now need to write ourselves
with Node JS so that we then, in a second step,
can have full control over how requests are parsed,
which data is extracted,
and which data is sent back as a response
because we no longer just want
to send back HTML files automatically.
The idea of using Node JS is that we have more control
than we did before over what happens on that server.
Now for that we will use certain features
that are built into Node JS.
You might recall this documentation.
I mentioned that Node JS comes with a lot of packages
that expose different features
that you can then use in your Node JS code.
For example, Node JS comes with the HTTP package
that gives us certain functionalities
that we can use in our code
to listen to incoming requests
and to send back responses.
And that is what we need to do
if we want to write our own web server.
We need to write some JavaScript code
that knows how to deal with incoming requests
and that knows how to then send back a response
so that we then can send requests in a second step
to that custom written web server with help of a browser.
So therefore back in app.js,
we will now start by using that built-in package
that helps us with that.
And we do this in our JavaScript file
by using a special keyword,
a special function that's built into Node JS,
called "require."
We execute this as a function by adding parentheses
after its name and then to "require" we pass a string.
And that string now contains the package name
that's built into Node JS that we want to use here.
And in this case, this will be the HTTP package,
which is a package,
for which you can view the documentation as well,
that offers certain functionalities
that help you deal with the requests and responses.
So for this, we require HTTP,
and calling this function will then return an object
full of utility methods and properties provided by Node JS.
So we store it as object in a constant now,
and I'll name this constant HTTP,
but this name is up to you.
We could also turn it into a variable,
but I don't plan on reassigning this to a different value.
And hence I can use a constant instead.
And these are all features we learned about before.
The only new thing here is the "require," a keyword.
This function, which is built into Node JS.
Now with that we are pulling in this HTTP object,
which is full of extra functionality.
And we can now use one of the built-in methods.
And for this, we use HTTP now
and here we can actually execute the create server method.
And this does what the name implies.
It will create a web server.
So even though we'll now not use some external company's
pre-configured web server,
we can still easily set up a custom server
with help of Node JS.
Now, just as a side note,
if we would want to host our Node JS-driven website,
we would still reach out to an external hosting provider
and upload our code to them.
The only difference would be
that we don't use a simple drag and drop hosting provider,
but instead we need a hosting provider
that offers us a computer
that already has Node JS pre-installed,
but we will come back
to deploying and hosting Node JS-driven websites later.
For the moment, let's focus on the code here.
And here we do now create a server
by executing this create server method here,
which exists on this HTTP object, which we do require here.
Now "create server" returns us an object,
which has all this server functionality
that is required under the hood built in.
And we can now store that in a number constant
or a variable, which I will call "server" here.
Now on that server that was created for us,
we can now call the built-in listen method.
And the idea here is that we first create a server
that knows how to handle incoming requests
and send back responses.
And then in the next step,
we start listening on a so-called port number.
Now that's a new concept.
And for that, let me quickly talk about addresses,
which we can enter in the browser to reach a website.
We can enter something like Amazon.com.
That's what we saw before.
And this will then send a request
to Amazon's servers or server,
which then returns the website.
Now when working with a network,
which is what we do when we do send requests,
then we also have the concept of ports.
And every computer has different ports,
which are basically entry points to that computer
that are either opened or closed.
Now by default, for most computers,
most ports are closed by default for security reasons,
because you want to have as little entry points as possible.
Now, when you send the request to Amazon.com,
by default, you send that to port 80,
which can also be expressed by adding a colon
after this name and then 80 here.
No, actually by default,
you typically use 4-4-3 to be precise
because that uses SSL,
which sends the request in a encrypted secure way.
But 80 is also a common port to send an unencrypted request,
and you can test this on your own.
If you enter Amazon.com, colon, 80,
and you hit enter,
you will see that you still visit amazon.com.
If you would instead enter Amazon.com, colon, 100,
it would fail instead.
So this really works.
And this port concept is important.
Now, 80 is the default,
which is why you don't have to enter it.
Instead if you just enter amazon.com,
it's basically sending this to port 80 or 4-4-3,
to be precise, as I mentioned by default.
The browser adds the port for you under the hood, so to say,
but when working with Node JS and creating your own server,
you need to let Node JS know
on which port you want to listen for incoming requests.
And for this cue, "listen," we pass such a port number
as a first parameter value.
Now by default,
we often use something like 3,000 here.
That is a port which is typically not opened,
but during development,
for playing around with our server
and testing whether everything works,
we typically want to use such a non-default port
so that we don't clash with any other services
that might be running on our local development machine.
That's why we pass 3,000 as a number to "listen"
to tell Node JS that once this code executes,
we want to create a server,
and we want to listen to incoming requests on port 3,000.
If we would then later deploy it as code
and move it onto a real remote machine,
which we rented from some hosting provider,
we would swap this for 80 or 4-4-3 in stat basically.
But for development, we can use something like 3,000.
And that was a lot of talking
about creating such a server and listening,
but it is super important that you do understand
what this code does,
because if you don't understand that,
understanding the other concepts will be very, very hard.
Now with that we are creating a server,
and we are listening,
but this server won't be finished yet
because whilst it will be a valid server
that's created here,
this server has no instructions
for what to do
if an actual request reaches it.
We don't define what our response should be,
or if we maybe want to extract some data
from the incoming request.
And the entire reason for using a server-side language
like Node JS is that we want to have more control
and that we maybe want to extract some data
from the incoming request.
And therefore as a next step,
let's now see how we can add more instructions here.