I'm trying to serve bootstrap locally via npm-installed package. However, Node is serving my html file in place of my bootstrap CSS and JS files. This is perplexing to me.
I'm specifying both folders to express.static to ensure they are accessible publicly:
app.use(express.static(path.join(__dirname,"public")));
app.use(express.static(path.join(__dirname, "node_modules")));
Here is my directory tree structure:
.
├── Assets
│ ├── 11-express-homework-demo-01.png
│ └── 11-express-homework-demo-02.png
├── Develop
│ ├── db
│ ├── node_modules
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ ├── notes.ejs
│ ├── index.html
│ ├── server.js
│ └── views
├── README.md
└── result.txt
wherein
server.js is where I'm running express from, node_modules is where bootstrap lives (default npm installation can be assumed)
and in both notes.ejs
and index.html
, I have the following resources included:
<link type="text/css" rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.min.css" >
<script type="script" src="/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
index.html is simply a static landing page and notes.ejs is the app's main user-interactive screen.
index.html is as follows:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Note Taker</title>
<link type="text/css" rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.min.css" >
</head>
<body>
<nav class="navbar bg-info">
<a class="navbar-brand text-light p-3" href="/">Note Taker
</a>
</nav>
<div class="container">
<div style="margin-top: 80px;" class="text-center p-5 mb-4 bg-light">
<h1 class="display-4">Note Taker <span role="img" aria-label="Memo"></span></h1>
<h4 class="mt-4">Take notes with Express</h4>
<a class="btn btn-primary btn-lg mt-4" href="/notes" role="button">Get Started</a>
</div>
</div>
<script type="script" src="/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
notes.ejs is as follows:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8" >
<meta name="viewport" content="width=device-width, initial-scale=1.0" >
<meta http-equiv="X-UA-Compatible" content="ie=edge" >
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<title>Note Taker</title>
<link
rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.3.1/css/all.css"
integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU"
crossorigin="anonymous"
>
<link type="text/css" rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.min.css" >
</head>
<body>
<nav class="navbar bg-info">
<a class="navbar-brand text-light p-3" href="/">Note Taker </a>
<div class="icons">
<i class="fas fa-save text-light save-note"></i>
<i class="fas fa-plus text-light new-note"></i>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-4 list-container">
<div class="card">
<ul class="list-group list-group-flush">
<%- titles %>
<!-- https://stackoverflow.com/a/33701518/9095603 -->
</ul>
</div>
</div>
<div class="col-8">
<input
class="note-title form-control form-control-lg"
placeholder="Note Title"
maxlength="28"
type="text"
>
<textarea class="note-textarea" class="form-control" placeholder="Note Text" style="min-width: 100%"></textarea>
</div>
</div>
</div>
<script type="script" src="/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
Addendum - also in case you needed to see my server.js:
// This application uses the Express.js framework to create a REST API that allows clients to perform CRUD (create, read, update, delete) operations on notes stored in a JSON file. The API has three endpoints:
// - `GET /notes` retrieves a list of all notes stored in the `notes.json` file.
// - `POST /notes` adds a new note to the list of notes stored in the `notes.json` file. The new note data is passed in the request body as JSON.
// - `DELETE /notes/:id` deletes a note from the list of notes stored in the `notes.json` file. The ID of the note to delete is passed in the URL as a path parameter.
const express = require("express");
const path = require("path");
const fs = require("fs");
// const bootstrap = require('bootstrap')
// import 'bootstrap/dist/css/bootstrap.css';
const app = express();
const PORT = 3001;
// EJS (alternatively use Pug for dynamic HTML)
// https://www.youtube.com/watch?v=yXEesONd_54
// register view engine
app.set("view engine", "ejs");
// inform ejs which is your views folder because you don't use the default folder name views, but rather 'public'
app.set("views", path.join(__dirname,"public"));
app.use(express.static(path.join(__dirname,"public")));
app.use(express.static(path.join(__dirname, "node_modules")));
var titles = "";
app.get("/notes", (req, res) => {
fs.readFile("db/db.json", "utf-8", (err, data) => {
if (err) {
res.status(500).send({ error: "Could not read file" });
} else {
data = JSON.parse(data);
// res.send(JSON.parse(data));
if (data) {
console.log(typeof data);
console.log(data);
for (let i = 0; i < data.length; i++) {
titles += `<li class="list-group-item">${data[i].title}</li>`;
}
console.log(titles);
}
}
});
// res.sendFile(path.join(__dirname,'public/notes.html'))
res.render("notes", { titles });
// render: https://youtu.be/yXEesONd_54?t=597
});
app.use((req, res) => {
res.sendFile(path.join(__dirname, "public/index.html"));
});
// app.get('/', (req, res) => {
// res.render('index', { title: 'some title'})
// })
app.listen(PORT, () => console.log(`Server is running on port ${PORT}`));
I have tried the above to no avail. In place of the linked bootstrap CSS file and the bootstrap JS file, it's serving my html file. I don't understand what is happening.