We're going to be super minimal today (since I haven't ate dinner yet and still have work to do :crying:) and build out a small "Hello, world!" file using the EJS template engine.
Any concepts you learn today can be applied to scale.
You should have the usual suspects for a NPM/Yarn project and require a Nodejs version that supports ES6 basics like destructing, arrow functions etc (basically any).
There has been much debate about the usage of templates at the places I have worked.
One benefit is that you can use them to scaffold the basics for you without the need for basically any manual work - think scaffold new components, routes, SCSS files etc.
Some argue that this can be overkill or not flexible enough, however I have found recently in increasinly large codebases that have been around for a few years, templates have been a great "source of truth" for enforcing particular coding patterns in our codebase and a great way for onboarding new developers into these patterns (and avoid them from copying the old!).
Initialise a new project and add three dependencies that we will use:
We are going to use yargs-parser to parse through our CLI arguments, fs-extra as an extension to Node's internal FS (it comes with some fun extra tidbits that we will use) and we're going to use ejs to render out our templates!
Let's make a
templates/starter folder from the root of our project.
Once created, add a basic
templates/starter/index.js file with the following:
What we are basically doing is calling the
main function straight away and logging out
argv is the result of our helper library Yargs Parser shifting through what we give it at the command line. If we run
node templates/starter/index.js, we should see the following:
We get an object with the key
_ and an empty array. What's going on here? Without going to deep into things (see the docs for a better explanation), anything passed into the command line after the first two arguments ("node" and "templates/starter/index.js") will be stored in the
_ array, and another other flag we pass ie
--flag=3 --test friend will be put under it's own key-value pair in the object.
Let's quickly test that now with
node templates/starter/index.js hello --flag=3 --test friend.
Perfect! We see our two flags add as their own key-value pair and anything else passed as an argument is added to the
We are going to use this to pass arguments to our simple template renderer.
Let's add the file
templates/starter/main.ejs file with the following:
Whoa, it looks like JS... but what is this funky syntax!?
That, my friends, is the EJS syntax. If we check the npm README, two of the features mentioned above are included:
Basically, we are running JS logic between the first feature we are using with the second feature resulting in our writing something to the template!
If this doesn't make sense just yet, do not fear. We are above to put it to good use.
templates/starter/index.js now and let's update our script to the following:
So now what is happening in our file? I've written them in the comments above, however here are them laid out together:
argvand set _ array to variable "data"
As for seven, that argument from the EJS docs looks as follows.
The arguments are that we want to pass the template filename to render (it will be the file path), the data that we wish to render in that template (for us it will be the
leftovers we wronte in the
main.ejs file earlier), we are just leaving the options as an empty object and finally we get a callback that gives us an error and string as arguments.
Sweet! Let's try some calls out!
First, let's see what happens when we are missing the
Peaches, now if we add both flags in?
We get the following logged out
Whoa! What's the JS? That's the
str variable being given back in our callback function from
ejs.renderFile! Super neat. Let's write that to a file!
Note: The spacing in the JS may look weird. I will address this later, but the solution will not be part of this tiny project.
We are going to use our help
fs-extra module to write this out!
fs-extra in the demo is actually a little OP (over-powered). It is a great library to know for sure though, so run with me on this one.
templates/starter/index.js to look like the following:
The only change now in the comments is at "Write file to --out path".
In those three lines, we are using path to join the current working directory (cwd) with the argument passed to our
Afterwards, we are using
ensureFileSync to ensure the paths to the file exists. We do this since if we passed
--out=path/to/main.js, we want to make sure the
to folder exist, otherwise it will fail. Our
fs-extra function abstracts that difficulty for us!
Finally, we write that file out.
Run the following one last time:
If you now check the root directory, you will see that
out.js has been generated! Crazy stuff.
Without even doing anything, let's run
node out.js and behold the power of the output:
out.js, we see the
str that we saw before has been written to the file:
Hooray! We are the greatest!
It is important to note that the above has some quirky spacing. This can happen when outputting the templates from EJS, so I always follow up in my own work by using Prettier.io. I am very, very hungry, so I am not going to add that last tidbit in tonight, but I highly recommend checking it out and trying it for yourself!
While this has been a super, SUPER basic entry into the world of templating, you can run off with this knowledge now and go as crazy as you want! Groovy templateing projects such as Hygen have used the same methods to a larger extent. Go forth with your witchcrazy and wizardy.
Image credit: Karsten Würth