node.js rendered page not loading styles

That’s my first-day learning Node.js and on making a basic server that basically renders 1 page containing a header tag, I get an error saying that the CSS file can’t be loaded

That’s my code:

const express = require('express');
const path = require('path');

const HOST = '127.0.0.1';
const PORT = 3000;

const app = express();

//app.use("/public", express.static(path.join(__dirname, "static")));
app.get('/', (request, response) => {
    response.setHeader("Content-Type", "text/html");
    response.sendFile(path.join(__dirname, "static", 'index.html'));
});

app.listen(PORT, HOST, () => {
    console.log(`Running Server on ${HOST}:${PORT}`)
});

The HTML file:

<!DOCTYPE html>
<html lang="en-us">
<head>
    <meta charset="utf-8">
    <title>Hello World!</title>
    <link rel="stylesheet" type="text/css" href="./css/index.css">
</head>
<body>
    <h1>Hello World From Node.js!</h1>
</body>
</html>

The Error: enter image description here

File Tree:

enter image description here

I just want to be pointed at the missing part here for the css file to be linked with the HTML

Note: the CSS file is loaded when I directly run the HTML by browser

Answer

You can use express.static() (that you commented out) to serve static files.

According to docs you need

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

This way CSS should load. Any request like http://127.0.0.1:3000/css/index.css will be checked against static directory and if matching file is found Express will serve it.

If request does not match the file in that directory (for example http://127.0.0.1:3000/) Express will continue to look for other matching routes and will execute app.get('/', fn) because it’ll match.

For reference, full code:

const express = require('express');
const path = require('path');

const HOST = '127.0.0.1';
const PORT = 3000;

const app = express();

app.use(express.static(path.join(__dirname, "static")));
app.get('/', (request, response) => {
    response.setHeader("Content-Type", "text/html");
    response.sendFile(path.join(__dirname, "static", 'index.html'));
});

app.listen(PORT, HOST, () => {
    console.log(`Running Server on ${HOST}:${PORT}`)
});

UPDATED There are two ways to use express.static() as docs explain:

When calling app.use(express.static(path.join(__dirname, "static"))); (without a prefix specified) index.css file, for example, will be available at

http://127.0.0.1:3000/css/index.css

When calling app.use("/public", express.static(path.join(__dirname, "static"))); (with /public prefix) the same index.css file will be available under /public prefix at

http://127.0.0.1:3000/public/css/index.css

This approach counter-intuitive because index.html needs to be updated to load CSS from this prefix (and will only work when loaded via http://127.0.0.1:3000/, not when opened as a local file):

<link rel="stylesheet" type="text/css" href="./public/css/index.css">