[Tutorial] An Introduction to Node.js Servers (and Express.js)

I’m not sure if there is a significant performance difference between the templating engines. I’d cache the output for anything that gets significant traffic. I’ll post a quick tutorial for that soon.

Here’s a quick example of how you can use Handlebars from scratch. (Change the Github username to change the output.) It’s just a couple of functions. I probably wouldn’t use Handlebars by itself like that on the frontend any more now, because you can do similar things with ES6 template strings.

If interested, you can also see how it’s used in Ember.js. (Handlebars is the templating system from Ember.)

1 Like

I started using mocha and chai up until 2019. Now I’ve been working with jest exclusively.

2 Likes

I guess this could now be a sub thread, as this thread is quite long, but I want to note something I figured out.

I am doing Server Side Render with Node, Express, and Handlebars. Then I am doing subsequent client side renders with vanilla JS.

It took me a while to realize it, but I can basically reuse the same controller file I use for the server side render with the API. :man_facepalming:

Basically if it is a request to the landing page I run the controller and then return the template. If it is a request to the API, I flag it as such, run the controller and return JSON.

Happy I caught it now at least! :slight_smile: It will save a lot of time and code repetition.

2 Likes

I am now trying to create a POST request to post a lot of JSON to my SQL table, but I am not sure how to use POST with the API structure.

I can see the data of my post request in the console here:

However, it seems that Express says it cannot get the “Post” request.

Here is what my route looks like:
//Custom user entered food router.get("/new-food-entry/", updateCtrl.newFoodEntry);

And then I am just trying to console the POST data in the controller for now
//Insert a new food into main nutrient DB function newFoodEntry(req,res) { console.log("req",req); res.send("OK"); }

I am not sure how to proceed with processing the data from this post request. Any help appreciated!

What is the exact message that Express gives you? If it literally says “cannot get post request” then it might be due to the wrong HTTP verb in the actual request. GET is a different verb from POST.

Hmm, well the first thing I was trying to do is open the API endpoint in the browser, which I guess is always a “Get” request, so that didn’t work.

Then I managed to figure out how post requests work.

Then there was a problem parsing the res.body, since apparently express does not include body parser anymore. I had to install that, and then it worked after following the instructions here:

2 Likes

Final code looks like this.
On the route file

var bodyParser = require('body-parser');
var jsonParser = bodyParser.json();
router.post('/new-food-entry', jsonParser, updateCtrl.newFoodEntry);

In the controller file

//Insert a new food into main nutrient DB
function newFoodEntry(req,res) {
  console.log("POST REQUEST",req.body);
    const user = {
     id: 'test',
     //name3: req.body.name3
    }
    res.status(201).json(user)
   }

As the StackOverflow suggests you need to:
npm i body-parser

1 Like

Nice. If you’re inserting data into the database from users, be extra careful to sanitize the inputs to avoid SQL injection problems. I included an example in my other sample code.

const sql = "SELECT * FROM monsters WHERE id = ?"; // use a question mark
connection.query(sql, [id], function (err, results, fields) {
// ...
1 Like

Good tip, thanks! :slight_smile: I am working on the SQL part of it now.

So as I am getting ready to deploy a site with Node and Express I am wondering what the usual best practice is in terms of deployment?

Should I create a new production folder and use gulp to just move over the files I need for the server while leaving dev files in the dev folder?

I am using Parcel as my bundler. I guess I can point parcel to create build files in the production folder too? For client side JS anyway…

I could look tomorrow. You can set conditionals in your templates based on whether the NODE_ENV environment variable is development or production.

// in the controller
const jsURL = process.env.NODE_ENV === "production"
    ? "/assets/js/build.js"      // if it's production, use this URL
    : "/assets/js/build.dev.js"; // otherwise use this URL

// ↑ send that variable into the handlebars template

Then in the template:

<script src="{{jsURL}}"></script>

or something like that.

NODE_ENV should be set to "production" on the live server.

1 Like

This is a great idea! Before I used to keep 2 folders, now I realize how little sense that makes…hmm…

I’m not sure if pm2 sets NODE_ENV by default but you could add this line to the bottom of your ~/.bashrc file on the remote server

# this sets an environment variable
export NODE_ENV=production

and it should load the correct URL.

Be sure to type this in the terminal after editing the .bashrc file to reload it:

$ source ~/.bashrc

This is how you read an environment variable in Node.js:

process.env.VARIABLE_NAME
1 Like

Am I right in thinking that when making database calls it is best to have all database results passed through an API URL so they can be cached on a CDN?

So when creating a controller function I would fetch data from the API as opposed to the database… any pitfalls with that thinking?

1 Like

If I understand how your site works, only the frontend code would access the API. If you want to cache internally, you could use Redis, but it might be overkill. It probably depends on traffic.

Maybe someone else here would know more about it. My sites don’t get enough traffic to do that — the outer-layer caches are enough.

1 Like

That is actually a great point I didn’t think about, thanks Josh! I guess I thought I might be able to access the API on server side render through. :thinking:

Right now I think Express redis cache could be causing some problems as I am getting quite a few 500s (13000 of them). No sure though. I will dig deeper into the logs.

Find me on Slack if you want to screenshare. I have a deadline tomorrow for the project I’m working on so I’m doing that tonight, but I’ll be around tomorrow.

You read my mind! Thanks for the offer. I am working on a work around for auth right now, but will be happy for advice tomorrow. :slight_smile:

Good luck with the deadline! :slight_smile:

1 Like

Is it common to use reddis for caching in express apps? Or just caching in general?

1 Like

Yeah, I think it is a database key value store that you can use to cache pretty much anything, anywhere. :slight_smile:

I think the problem I was/am hitting with redis is that I use query parameters in the URL like

foods.php?foodid=1

Instead of
foods/foodid

So when I change that format, it should be better… :crossed_fingers:

2 Likes