Home > Software engineering >  How to serve static HTML files with vanilla javascript including submodules?
How to serve static HTML files with vanilla javascript including submodules?

Time:07-18

I want to serve a static html file with elements defined in a javascript file using imports from submodules. How is this possible with vanilla JS? Or do I need some bundling tools and / or other frameworks? Example code structure to illustrate my intention:

index.html

<html>
  <div id="screen">
    <div id="grid"></div>
  </div>
  <h1>Example</h1>
  <body>
    <script type="module" src="index.js"></script>
  </body>
</html>

index.js

import { buildGrid } from "./buildGrid.js"
var http = require("http");
http
  .createServer(function (req, res) {
    fs.readFile(__dirname   req.url, function (err, data) {
      if (err) {
        res.writeHead(404);
        res.end(JSON.stringify(err));
        return;
      }
      res.writeHead(200);
      res.header("Content-Type", "application/javascript");
      res.end(data);
    });
  })
  .listen(8080);

buildGrid();

buildGrid.js

export function buildGrid() {
    let grid = document.getElementById("grid");
    let cell = document.createElement("div");
    cell.className = "cell";
    cell.textContent = "test;
    grid.appendChild(cell);
}

style.css

body,
html {
  background: #111;
  color: white;
}
#screen {
  display: flex;
  flex-direction: column;
}
.cell {
  width: 30px;
  height: 30px;
  background: #2d2f34;
}

CodePudding user response:

Splitting the code to a server part and a client part solved my issues, as correctly pointed out in the comments.

So all the server handling was placed in a server.js file, while the client specific content (which is to be injected into the index.html file) was placed in the index.js file.

Furthermore, I also utilized submodules to separate different parts of the index.js file. So it was need to specify <script type="module" src="./index.js"></script> on the import in the index.htmlfile. And in the server.js file, the different file types were handled by setting the header based on the file type in the request. Hope the following will be of help for others serving HTML with JS modules using nodejs.

So the end file structure was like this

  • server.js
  • index.js
  • buildGrid.mjs
  • style.css
  • index.html

server.js

"use strict";
var http = require("http");
var fs = require("fs");

function readFile(req, res) {
  var filePath = __dirname   req.url;

  fs.readFile(filePath, (error, data) => {
    if (error) {
      res.setHeader("Content-Type", "text/html");
      res.writeHead(404);
      res.write("Not found error 404");
      res.end();
    } else {
      const url = req.url === "/" ? "/index.html" : req.url;
      if (req.url.includes("js"))
        res.setHeader("Content-Type", "application/javascript");
      if (req.url.includes("css")) res.setHeader("Content-Type", "text/css");
      if (req.url.includes("html")) res.setHeader("Content-Type", "text/html");
      res.writeHead(200);
      res.write(data);
      res.end();
    }
  });
}

http
  .createServer(function (req, res) {
    readFile(req, res);
  })
  .listen(8080);

index.html

<html>
  <h1>Example</h1>
  <div id="screen">
    <div id="grid"></div>
  </div>
  <head>
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <script type="module" src="./index.js"></script>
  </body>
</html>

index.js

import { buildGrid } from "./buildGrid.mjs"
export function main {
 buildGrid()
}

buildGrid.mjs

export function buildGrid() {
    let grid = document.getElementById("grid");
    let cell = document.createElement("div");
    cell.className = "cell";
    cell.textContent = "test;
    grid.appendChild(cell);
}

style.css

body,
html {
  background: #111;
  color: white;
  font-family: sans-serif;
}
#screen {
  display: flex;
  flex-direction: column;
}
.cell {
  width: 30px;
  height: 30px;
}
  • Related