So far in our code we've been using and requiring all of these Node modules for example EJS or Express 1
and body-parser. 2
But how does it actually work? 3
If we take a look inside our Node modules and we go and just find where EJS is, and we click on 4
ejs. 5
js, if you scroll down it, you can see that there is-- maybe there are some variables which we already 6
know about, there's some functions but there's also a whole bunch of these exports: exports.this export. 7
that. 8
So what exactly is that? 9
Let's try and understand how our Node modules like EJS, Express, body-parser actually work by creating 10
a module of our own from scratch. 11
Currently we have this thing down here which basically just generates the current day in a particular 12
format that we desired. 13
Now if we were to refactor our code right now then this is probably one of the first things that we 14
want to package into its own module because it doesn't really belong here in the app.js. You can imagine 15
that as our app.js gets more and more complex, then we have more routes, 16
we have different get, post routes all over the place. 17
Code that's not strictly related to the route shouldn't actually be in here cluttering the app. 18
js. 19
How would you normally solve this? 20
Well we could go ahead and create a new file 21
let's just call it date.js and this could be our own little module for generating the current 22
date. 23
So let's go ahead and cut all of this code. 24
And we're going to paste it inside date.js. And of course we have to again say jshint we're 25
using esversion 6. 26
Now we have this date.js module which does all of the hard work to find the date and change it 27
to a particular format. 28
But how do we get this day back into our app. 29
js and use it inside our root route? 30
Well maybe we could wrap this thing inside a function, we could call it getDate. And this function 31
all it does is carries out all of this code and then it simply returns the result of all of this. 32
So at the end we get this thing called Day which is what we've been previously using inside our root 33
route. 34
So what if we just returned day 35
so we get an output out of our function? 36
Now we have this function and we have a way for it to return the thing that we want. 37
How do we actually export it? 38
How do we get it out of this date.js? 39
How can we make it available elsewhere if it's needed? 40
Well this is where Node comes in to the rescue. 41
So if you take a look at the docs for the latest version then if you read through all of this maybe 42
not all of it but the relevant parts, then you can see that there's a section on modules. And the module 43
object is basically something that gives you a reference to the object that represents the current module. 44
So that means that inside this module here date. 45
.js, we have access to this thing called module. 46
And I can go ahead and just log my module. And if I were to use this module then I can require this module 47
to run all the code inside here. 48
So for example, up here instead of requiring body-parser and Express I'm going to create a new const called 49
date and this simply requires my new date module. 50
Now because our module is local and has not installed using NPM then the way we access it is a little 51
bit different. 52
We have to use that thing that we saw previously with the directory name + 53
and then we have to locate our date.js. 54
So now what this will do is we're saying we're requiring a module and it's located at the current directory 55
name and then we add /.js in order to access this particular file. 56
So now if I hit save and I run my code using node app.js making sure that you're in the right 57
position then I will end up with my module printed out inside my console. 58
So whenever I say require this module then it'll go into this module and it'll try to run all of this code. 59
Now over here you can see what it's running is that log statement. And we've logged that module object 60
so this is the object that represents our date module. And you can see it's got a whole bunch of interesting 61
things in here. 62
For example an id 63
so this is where it's located which currently is in my local directory right? Something called WebDev 64
/todolist-v1/date.js which is where you can see it here. 65
And then you've got a whole bunch of other things such as 66
it's got a parent module right? 67
What was the model that actually launched it or required it? 68
Well in this case it's something called app.js. And that thing has a whole bunch of children including 69
this date module. 70
So we've also got other children such as Express and body-parser and EJS and it's also got other things 71
associated to it. 72
Now if we take a look at our module object that represents our date module you can see it's also got 73
this property called exports. And export seems to be some sort of Javascript object as denoted by those 74
curly braces. 75
But at the moment it's completely empty. 76
So there is nothing that our module is exporting. 77
If we take a look back at the documentation and we navigate to this part where it talks about module 78
.exports, then you can see that this is also a Javascript object and it's created by the module system. 79
So what it allows us to do is to basically say module.exports do something or is equal to something. 80
And then that means that in another file, we can simply tap into that module and use some of those exports. 81
So let me show it to you in our code. 82
Now instead of console logging our module, we can simply write module.exports. 83
Remember the s 84
this is a really common mistake. 85
And then we set it to equal say hello world 86
maybe. Now this current date module exports the string that's Hello world. 87
So if we go back into our app. 88
js whenever we require our module it gets bound to something called date. 89
And over here we can simply log our date object and that will be equal to whatever it is that we exported 90
out of this module. 91
So now if I had back into my console and I stopped my server and rerun it, you can see that my app. 92
js is now printing 93
Hello world. 94
There's no log statements over here. 95
And this is because I'm exporting from this module 96
just a simple string and it's now available inside my app. 97
js. Now they were able to get access to the exports from this module, 98
what if we wanted to get access to a function instead? 99
For example what if we wanted to be able to tap into this function? 100
Well if instead of setting our module.exports to equal hello world, we can set it to equal getDate. 101
Now the important thing with Javascript object is when you decide to add the parentheses because the 102
time when you add the parentheses then that means we're actually calling, we're activating the function 103
right? 104
And we don't want to do that inside our module because we want to allow the app.js to determine 105
when that function should be called. 106
So currently our date object here is bound to the exports of our date module and the exports of our date module 107
is simply just a function. 108
So if I were to log date as it is right now, you can see that it's only going to tell me that it's just 109
a function and it's called getDate. 110
It's not going to actually run that function and give me the return statement which is the actual date 111
that I'm looking for. 112
If I want it to run then I have to add my parentheses. 113
So now when I rerun my app.js you can see now it's running the function get date rather than just 114
logging the actual function. 115
Now by binding our exports to this function inside the module, we're now able to export it into our app.js 116
and we can use it anywhere we like. 117
So we don't have to activate it when we require it, 118
we can add it wherever it's needed. 119
So for example inside our app.get, we're now able to say date run or whatever is bound to that module 120
and let's say we save it inside something called day 121
right? 122
So now we have this thing called day which is bound to the output of this date module which currently 123
is getting us the current date because it's running this function getDate. What we're saying here 124
is we have this module called date and we're requiring it up here which binds all of the exports to this 125
constant called date. And then down here we call the function that's bound to that constant date and we 126
activate our getDate function. And now we have the result of it stored inside day which we're going 127
to pass over here. 128
Now we're able to head over to our console and run our app.j 129
js. 130
And now if we head over to our localhost:3000, you can see it's passing the output of that date module 131
into our title over here. 132
So we've managed to move our date code out of our app.js put it into its own separate module and 133
we're able to use it inside app.js or any other file for that matter. 134
And now this code in our date.js is completely reusable. 135
We can require it and use it anywhere we like. 136
But what if we wanted our date module to do more than one thing because at the moment all it exports 137
is just one function right? 138
It kind of makes its functionality quite limited. 139
What if we had say another function right? Down here. Let's say we had a function, instead of getdate 140
it's gets the day right? 141
The current day of the week. And pretty much all of this is the same 142
other than this option we only want the weekday to be in a long format and then we bind it to this thing 143
called day and we return it as the output of this function. 144
Now because our module.exports is only bound to getDate to function, we can't seem to access this 145
getDay. 146
How do we solve this? 147
Well if you remember previously I mentioned that module.export is a Javascript object. 148
And objects have properties and methods associated with it. 149
So that means that instead of simply binding the entire object to our getDate function, I could say module 150
.exports.geDate is equal to this function. And that means that I can do the same thing down 151
here and say model.exports.getDay is equal to the getDay function. 152
So now if at the end of all of this code we log our module.exports and we go back into our app. 153
.js and require that module, 154
then you can see that currently our exports object now has two functions that are tied to it. 155
One is called getDay and one is called getDate. Now inside our app.js, instead of saying just run 156
the function that's bound to the exports from our data module 157
we can say run the function that's bound to our date module .getDate. 158
And this will work exactly the same way as before 159
so I can restart my server and you can see that it's still working as expected 160
but now I have the option of saying, 'Oh maybe instead I just want the actual day of the week.' 161
So now if I go ahead and restart my server and refresh my website, you can see I'm using the getDay 162
function inside our date module to just bring up the actual day of the week. 163
This is how we can create our own modules and require them and get their functionality exported out of 164
the module to be used anywhere within our project. 165
So this makes it reusable and way more useful. 166
So this is the first step in our refactoring. 167
Now the next step is how can we make this a little bit more succinct? 168
How can we make it a bit shorter 169
because at the moment it's quite wordy 170
right? 171
So for example here where we're creating let day equals this and then return day, then we can simply 172
get rid of all of this and just say return this 173
right? 174
So we can now delete that and we can do the same over here. 175
We can simply just return that without having to bind it to another variable. 176
The next thing we can look at is for example here we're saying module.export.getDate equals 177
getDate function getDate this getDate-- like all over the place 178
right? 179
So how can we simplify this? 180
Well you might remember from earlier lessons that we mentioned that Javascript functions can be declared 181
in a variety of ways. And in the course resources a link to this particular blog post which does a really 182
good job of summarizing the 6 different ways that you can declare Javascript functions. 183
So there's a lot of different ways that you can do it. 184
Now the way that we're most used to is just a simple function declaration. 185
It's the function keyword, the name of the function, some inputs and maybe some outputs 186
right? Now another way of doing this is by using a function expression. We could set our function to equal 187
a variable instead. 188
And this means that we can pass our function around whenever we need it. 189
So now we have an anonymous function that's set to equal a variable with a name 190
and whenever we need that functionality we simply just refer to it by its name. 191
So let's implement it to understand it a bit better. Instead of having our getDate as a normal Javascript 192
function, 193
I'm going to change it into an anonymous function so this function doesn't have a name anymore. And instead 194
we're going to bind it to a variable that's called getDate. 195
And now this getDate variable is bound to our anonymous function. 196
And you can see now this is a little bit clearer. 197
Instead of saying module.exports.getDate = getDate which is basically the contents of 198
everything after the equal sign, 199
then we can simply delete all this and say module.exports.getDate is now equal to this anonymous 200
function. 201
And this means that we save on two get dates and we make everything a little bit more succinct. 202
Let's go ahead and do the same thing over here. 203
Let's delete this name of the function to turn it into an anonymous function 204
and we're simply going to set that function to equal module.exports.getDay. 205
Now we can make this even shorter by reading through our node.js documentation because if you scroll 206
down a little bit, you can see that node.js actually provides an export shortcut because just how often 207
it's used. 208
So instead of using module.exports we can simply just use the exports variable to refer to exactly 209
the same thing. 210
So here instead of saying module.exports, we can just say exports for short and it will refer to 211
the same thing which is module.exports. 212
So now let's hit save. 213
I'm going to delete this console log 214
and over here in my app.js I'm using date.getDate from my date module and I'm rendering it 215
as my list title. 216
So if we go ahead and launch our app now with nodemon to save ourselves the effort of restarting our 217
server all the time, then we can refresh and you can see our app works exactly the same. 218
Now while refactoring, we might as well try and refactor the rest of our code. 219
For example we've got a lot of let around here. 220
So these are variables but actually these variables are never going to vary. 221
So we can simply change it to const, const here as well 222
and const down here. Now because we're never really re-assigning the values of today or options, then 223
this won't change our code at all. 224
It still works exactly the same way. 225
Now back in our app.js we can do some more of that refactoring. 226
For example here where we're changing the items array into a const and you might say hey wait a minute, 227
what-- we're going to change this right? We're going to add new items to this array. 228
So how do we make it a constant? 229
Well this is a little bit of a quirk of Javascript and it's not this way in some languages 230
and it varies from language to language. But for Javascript at least, if you take a look at the MDN docs 231
for const and you scroll down at some of their examples, you can see that when they talk about arrays 232
when we create a constant which is an array, it's actually possible to push new items into the array. 233
But it's not possible to simply assign it to a brand new array. 234
This is one of the things that doesn't really stay constant. 235
The other thing that doesn't stay constant is when you have an object and you can't change that object 236
into an entirely new object 237
right? 238
This will throw an error because my object was declared as constant. 239
But if you try to change one of the values that's associated with one of the keys inside the object, 240
then you actually can 241
even though this thing is a constant. 242
So it's important to remember that when you declare something as constant in Javascript it's not protecting 243
the things that's inside that thing, 244
so inside the array or inside the object. You're still able to vary those things. You just can't assign 245
it to a new entirely different object or array. 246
So that means over here if we change all of those lets to consts, then it will still work just as well 247
and we won't actually come into any problems. 248
So let's hit save and nodemon's updating our server behind the scenes. And refresh our website 249
you can see that we're still getting the data here and we're still able to add items into our array 250
and cross them out as needed. 251
So I hope you enjoyed learning about EJS and templating with me in this module. In the next module we're 252
going to see if you can apply everything that we learned about EJS and templating into your very own 253
project. 254
So head over to the challenge once you're ready.