Step 12

Static files are files such as images, CSS files, and even JavaScript files shared among your HTML pages and do not change during runtime due to user interaction (hence, "static").

Express makes it very easy to serve static files. Let's refactor the index.html and separate the styling and script elements into their files to see it in action.

Extract style element
  1. Create a style.css file with the following content.
.input-block {
  width: 100% !important;
  margin-right: 0 !important;
}
  1. Remove the <style> element from index.html and instead link to the style.css file.
<link href="style.css" rel="stylesheet" />
Extract script element
  1. Create a script.js file with the following content.
document.getElementById("submit").addEventListener("click", validateForm);

const age = document.getElementById("age");
const height = document.getElementById("height");
const weight = document.getElementById("weight");
const gender = document.getElementById("gender");

const output = document.getElementById("output");
const result = document.getElementById("result");
const bmi = document.getElementById("bmi");

function validateForm(event) {
  clear();
  event.preventDefault();
  if (
    age.value == "" ||
    height.value == "" ||
    weight.value == "" ||
    gender.value == ""
  ) {
    output.className = "flash flash-error";
    result.innerText = "All fields are required!";
  } else {
    calcBmi();
  }
}

function clear() {
  result.innerHTML = "";
  bmi.innerHTML = "";
  output.className = "";
}

function calcBmi() {
  const p = [age.value, height.value, weight.value, gender.value];
  const bmiVal = Number(p[2]) / (((Number(p[1]) / 100) * Number(p[1])) / 100);

  if (bmiVal < 18.5) {
    output.className = "flash";
    result.innerText = "Underweight";
  } else if (bmiVal <= 24.9) {
    output.className = "flash flash-success";
    result.innerText = "Healthy";
  } else if (bmiVal <= 29.9) {
    output.className = "flash flash-warn";
    result.innerText = "Overweight";
  } else if (bmiVal <= 34.9) {
    output.className = "flash flash-error";
    result.innerText = "Obese";
  } else {
    output.className = "flash flash-error";
    result.innerText = "Extremely obese";
  }

  bmi.innerText = "BMI: " + parseFloat(bmiVal).toFixed(2);
}
  1. Remove the <script> element content from index.html and instead link to the script.js file.
<script src="script.js"></script>

Next, move the index.html, style.css, and script.js to a sub-folder, app, to separate the app from the server files.

Finally, update the server.js file as follows:

  const path = require("path");
  const express = require("express");
  const app = express();
  const port = process.env.PORT || 7000;

+ app.use(express.static(path.join(__dirname, "app")));

  app.get("/", (req, res) => {
-   res.sendFile(path.join(__dirname, "index.html"));
+   res.sendFile(path.join(__dirname, "app", "index.html"));
  });

  app.listen(port, () => {
    console.log(`Express app listening at http://localhost:${port}`);
  });

The express.static is a built-in middleware function in Express. It serves static files.

Save the file and run it:

node server.js

Open the browser and visit http://localhost:7000/. You should see the BMI calculator app.

Save changes, commit and push your code. Then, make sure the Heroku App is working as expected!