Now, EJS is really, really useful here
since it allows us to generate dynamic content.
And that is one of the main reasons
for using server-side code, as you learned.
Now, there is another kind of use
we can get out of that templating engine.
Even besides this dynamic content,
we can use this templating engine that we have installed
to make our life as a developer a bit easier.
In all our HTML files,
or now EJS files,
we have that shared header and aside part here.
It's the same in every file, and that was annoying before
when we had to change all these links in all the files.
You wanna avoid something like this as a developer
because whenever you duplicate code
across different functions or files,
it means that any change to that code
needs a lot of adjustments in a lot of places,
as you saw here at the example of these links
which we had to adjust.
Now, EJS has a feature called includes
that helps us deal with that problem.
Now, what is an include?
An include is basically another EJS file
that contains a part of a page
which you then potentially can use on multiple pages.
And you can use includes to split your big HTML files
into smaller, more manageable pieces.
For this, I'll add a new subfolder in the views folder,
and that is the includes folder here for me.
Now, in this includes folder,
we can, for example, add a header.ejs file.
And my idea now is that I grab my header here
from any of the other EJS files,
and I cut this header,
this header HTML code,
and add it in header.ejs.
Now, this is not a complete HTML page
but only a part of an HTML page.
And in about.ejs,
we can now include this partial that we created here.
In about.ejs, in the place where we wanna have the header,
we can use another special syntax offered by EJS,
and that is smaller than, percentage sign, dash,
and then also the closing tag without a dash.
The dash is another EJS syntax,
which we haven't seen before,
which we use whenever we wanna render some HTML content.
Because by default, and that's important,
if we output something as we did it before
with that equal sign,
then EJS will take the value stored in there
and output it as raw text.
So even if I did share a restaurant
where I tried to be tricky and add some HTML code here,
once we output that description,
it would be output as raw text.
It would not be interpreted as HTML by EJS.
This is also security mechanism
so that for pages with user-generated content,
your users can't start injecting HTML pieces into your page.
That could become dangerous as soon as they start injecting
images that load other parts of other sites
or as soon as they start injecting scripts.
That's why the equal sign does something
which is called escaping.
It escapes that value that it outputs,
which means it translates it into raw text.
That's useful for outputting such user-generated content.
It's not useful for including some HTML code
that we store in a different file.
There, instead, we wanna use the minus
which does not escape that content
but which instead will actually treat HTML code
as HTML code instead of raw text.
And we need that because we'll now use a special function
that is provided by EJS,
and that's the include function.
The include function allows us to specify a path
to a different EJS file,
and EJS will then parse that file as well
and get the HTML content generated by that file.
And because of that EJS tag with the dash here that we use,
that HTML content will then be injected
and treated as HTML content in this overall HTML page.
Therefore, you now need to pass a value to include,
which should be a string,
which is the path to the file that should be included.
And by default, you can use a relative path here
seen from the template file
in which you are using this function,
so in this case, seen relative from about.ejs,
and that could be includes/header here,
again, without the extension.
As a second value, you could also pass in
an object with extra values for that path, for that file,
just as we do it in app.js when we called render.
There, we can also pass in an object with data
that is available in the template.
If you need such data in the included file,
you can pass such data to the include like this as well.
But here the header has no dynamic content,
hence I don't need to pass any dynamic data to it,
and hence I can just include it like this.
And with that, if we save this,
if we now go to the About page, it still works,
and we still have the header with the navigation here.
And if we inspect this, we also see no real difference
compared to the other files,
but this header actually was included
with help of this include function.
And, of course, now I wanna do the same
with the header in all the other files
and also for this side drawer.
Definitely feel free to do this on your own first
as a practice.
In a couple of seconds, which I give you to pause the video,
we'll do that together.
So were you successful? Let's now do that together.
And I'll start with the header.
Of course, that should be fairly straightforward.
We just copy this include code from about.
And then in all the other EJS files,
we replace this header code with this include,
also here in index
and in recommend, of course, as well.
So here I also replace that.
And then in restaurants.ejs, I also wanna replace that,
like this.
Now I also wanted to do the same for the side drawer.
We could have included it in the header partial,
but I will create a separate includable file,
copy the aside from any EJS files
since it's always the same,
and then add a side-drawer.ejs file in this includes folder,
store the content here, and then start including this
simply by copying this include code
and replacing aside with it.
Now we just need to include the side-drawer here.
And then we can, again, repeat that
in all the different EJS files
so that we include that in all those files.
So let's do this.
And with that, we already reduced the amount of code
in all those files quite a bit.
And that is something you wanna strive for as a developer
because the bigger your web projects get,
the more complex your HTML code will get.
And if you then have
small, reusable, includable files like this,
you don't just avoid a bunch of copy and pasting,
but you also have more manageable files
where you will be quicker to find
the exact code you now need to work on.
So splitting your code like this
does not just avoid unnecessary duplication.
It can also make structuring your project
and working on your HTML code easier.
Keep in mind that we did, for example, also split
our style files.
For HTML, we had no such mechanism before.
Now, with the templating engine, we do have it.
So extra maintainability is another benefit here.
And speaking of that, there are more parts we can include.
For example, the head section here is also pretty similar.
There are some page-specific imports,
some page-specific CSS imports,
but there also is a lot of shared content,
and therefore I'll add an include here, head.ejs.
And then from about.ejs,
I'll take all the content from the head section here,
cut it, and add it in head.ejs.
This might look strange because we got some metadata now
in a file without the head wrapper around it.
But keep in mind that ultimately this will be injected
between the head tags again
because now here in about, I can include head,
not header but head here in the head section.
I can do this in the other files as well, so I'll copy that,
and in confirm.ejs, I'll do the same, like this.
In index.ejs, I'll also do that,
but there, I also got a page-specific CSS file,
and therefore I'll leave that specific file here
and just replace the other parts with that included head.
And that's how we can then still have page-specific styles
merged with that main head
that is the same for all the pages.
It's the same for recommend.ejs.
I do have this page-specific CSS file which I'll keep,
but I will replace the other content here
and do the same for restaurants.ejs.
Keep the specific file
and replace the other parts here like that.
Again, if we save this, it still works.
The styles still are there.
We also got no error here in the Network or in this Console,
and we can also still open that mobile menu,
but now we got more code reusage and leaner EJS files.
There is one last piece of code that I'd like to include,
and that is actually my restaurant-item.
I only use that in one file,
so I don't wanna turn this into an include
to avoid code duplication.
But I wanna turn it into an include
to make this restaurants.ejs file even leaner
and therefore more manageable
and at the same time to make this restaurant-item
leaner and easier to find.
And therefore, I'll cut this list item from restaurants.ejs,
and in includes I'll add a subfolder restaurants
just to make it clear that there
I have some specific includes for a specific page.
It's not technically required
but makes it easier to find this specific include later.
And in there I'll add
my, let's say, restaurant-item EJS file.
And in there I now have this included list item code.
But the tricky thing now
is that in there I do actually have some dynamic data.
But I did mention before that for includes,
you can also pass dynamic data into includes.
So back here in restaurants.ejs, instead of the for loop,
I now wanna start by including again,
by calling this include function.
And I wanna go to includes/restaurants here,
oops, restaurants, and then restaurant-item.
And I'll now pass this second parameter value
to this include function
to provide a restaurant key to this included code
because here I'm referring to this restaurant key
in this restaurant-item.ejs file.
So I'm providing this key here now in restaurants.ejs.
And the value for the key is this restaurant here.
And I know that's a lot of restaurants,
but I hope I could make it clear
which restaurant refers to what.
This restaurant here is this constant,
so it's one of the restaurant objects
in this restaurants list.
On the other hand, this restaurant here
is simply the key name
that is now made available to restaurant-item.ejs,
which is where I'm using this key in all these places here.
So that's this restaurant key which I'm accessing
and which therefore needs to be made available.
That's this first key.
With that, we can again save this.
And still, if we reload this,
everything works the way it did before.
We can still see our restaurants here. Everything renders.
But we now get a even leaner restaurants.ejs file
which, as mentioned, is something we typically strive for
as a developer
because if we now had more content in this file,
we could put these different parts also into other includes.
And if we then ever need to work
on the HTML code of a restaurant-item,
we can go to that specific file
and work on it just like this
instead of having to search for this list item
in a potentially pretty big restaurants.ejs file.
That's why splitting the code like this
could also be something that's interesting.
And with a templating engine like EJS,
it's super easy to do.