0

I would like to know how to pass the "myBlogs" variable that I have in my Node.js file ("server.js") to a frontend JavaScript file ("blogs.js"). Once I have access to it in the JS file, I would then map through the array that is stored in that variable and output a template for each blog in an HTML file ("blogs.html").

Later, the idea is to get the blogs data from a database (MongoDB) instead of having them hard coded. I have seen how to do this with Express and a templating engine (EJS), but as practice for a beginner, I would like to understand the basics of if and how it can be done without these tools.

My file structure:

blogs.css
blogs.html
blogs.js
server.js

server.js:

const http = require("http");
const fs = require("fs");
const myBlogs = [
  {
    title: "My first blog",
    author: "John",
  },
  {
    title: "My second blog",
    author: "Mike",
  },
];

const server = http.createServer((req, res) => {
  console.log("request made");

  // set header content type
  let path = "";
  switch (req.url) {
    case "/blogs.css":
      path += "blogs.css";
      res.setHeader("Content-Type", "text/css");
      break;
    case "/blogs.js":
      path += "blogs.js";
      res.setHeader("Content-Type", "text/javascript");
      break;
    default:
      path += "blogs.html";
      res.setHeader("Content-Type", "text/html");
  }

  // send file
  fs.readFile(path, (err, data) => {
    if (err) {
      console.log(err);
      res.end();
    } else {
      res.write(data);
      res.end();
    }
  });
});

server.listen(3000, "localhost", () => {
  console.log("listening for requests on port 3000");
});

blogs.js:

const container = document.querySelector("div")


const html = myBlogs.map(blog => (
    `<h2>${blog.title}</h2>
    <p>${blog.author}</p>`
))
container.innerHTML = html;

blogs.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="blogs.css" />
  </head>
  <body>
    <div></div>

    <script src="blogs.js"></script>
  </body>
</html>

blogs.css:

p {
    color: red;
}

P.S.: If such an approach is completely wrong, could you please explain the correct way this would be done without the use of Express and a templating engine?

2 Answers 2

1

server.js

  // send file
  fs.readFile(path, "utf8", (err, data) => {
    if (err) {
      console.log(err);
      res.end();
    } else {
      res.write(data.replace(/%MY_BLOGS%/g, JSON.stringify(myBlogs)));
      res.end();
    }
  });

blogs.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="blogs.css" />
    <script>
       var myBlogs = %MY_BLOGS%;
       console.log(myBlogs);
    </script>

  </head>
  <body>
    <div></div>

    <script src="blogs.js"></script>
  </body>
</html>

This is incredibly hacky and not a good practice at all. It basically just finds %MY_BLOGS% and interpolates a JSON encoded object. Since JSON is valid JS, it will be directly accessible in your client side JS. You can now access myBlogs in blogs.js since it's a global variable.

Sign up to request clarification or add additional context in comments.

3 Comments

I don't think it's hacky. I would even say it's a common way. But I would prefer a template engine.
Thank you for your reply. I have tried this code, but am getting the following error: res.write(data.replace(/%MY_BLOGS%/g, JSON.stringify(myBlogs))); ^ TypeError: data.replace is not a function at FSReqCallback.readFileAfterClose [as oncomplete] (node:internal/fs/read_file_context:68:3) Can you please advise how to fix it? Thanks
@Hvalur123 Sorry, I forgot to add the utf8 encoding to the readFile call. I updated my answer. Data was returning a Buffer instead of a string hence why replace didn't exist.
0

Instead of using HTTP you could use something like express.js with ejs to pass backend data to front end.

npm i express ejs

Now you have express.js and ejs installed write some simple code like this:

server.js

const express = require('express')
// Create new server
const app = express()

// This will read read all the files in static and add them eg;
// static/style.css would now be able to do localhost:3000/style.css
app.use(express.static("static"))
// Set the view engine from text to ejs
app.set('view engine', 'ejs')


// app.get means you are using the get method on the url "/"
app.get('/', (req,res) => {
  // res.render is the method for ejs
  // res.render(file, options)
  res.render('blogs', {
    // Now on the front end you would be able to get data
    data: example
  })
})

// Start listening on X port
app.listen(3000, () => { 
  console.log("Listening on port 3000")
}) 

views/blogs.ejs

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="blogs.css" />
  </head>
  <body>
    <div>My blogs <%= locals.data %></div>
  </body>
</html>

In ejs you use <% %> to run something and <%= %> to output something

Your project structure would look something like this:

static
  blogs.css
  blogs.js
views
  blogs.ejs

server.js

You should read up on express.js and ejs

1 Comment

OP specifically said he/she doesn't want to use EJS and express "I have seen how to do this with Express and a templating engine (EJS), but as practice for a beginner, I would like to understand the basics of if and how it can be done without these tools."

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.