Skip to content

server.js HTML cache never invalidates when files change on disk #281

Description

@rishab11250

Description

The serveHtml() function (server.js:83-97) caches HTML file contents in the htmlCache object indefinitely on first read. If any .html file is modified after the server starts, the cache returns stale content until the process is restarted.

This is especially problematic during development — edits to leaderboard.html, user.html, etc. require a manual server restart to take effect.

Affected Code

const htmlCache = {};
function serveHtml(res, filePath) {
  if (htmlCache[filePath]) {
    const html = htmlCache[filePath].replace(/__NONCE__/g, res.locals.nonce);
    return res.type("html").send(html);  // ← always returns cached version
  }

  fs.readFile(filePath, "utf8", (err, data) => {
    if (err) return res.status(500).send("Error loading page");
    htmlCache[filePath] = data;  // ← never invalidated
    const html = data.replace(/__NONCE__/g, res.locals.nonce);
    res.type("html").send(html);
  });
}

Steps to Reproduce

  1. Start the server (npm run dev)
  2. Edit frontend/leaderboard.html (add a test comment)
  3. Refresh http://localhost:3000/leaderboard
  4. The change does not appear — old cached version is served
  5. Restart the server — change now appears

Expected Behavior

File changes should be reflected without a server restart during development. The cache should either use mtime validation, or be disabled when NODE_ENV=development.

Suggested Fix

Option A — Check file modification time on each request:

const htmlCache = {};  // { filePath: { mtime: Date, data: string } }

function serveHtml(res, filePath) {
  fs.stat(filePath, (err, stats) => {
    if (err) return res.status(500).send("Error loading page");
    const cached = htmlCache[filePath];
    if (cached && cached.mtime >= stats.mtimeMs) {
      return res.type("html").send(cached.data.replace(/__NONCE__/g, res.locals.nonce));
    }
    fs.readFile(filePath, "utf8", (readErr, data) => {
      if (readErr) return res.status(500).send("Error loading page");
      htmlCache[filePath] = { mtime: stats.mtimeMs, data };
      res.type("html").send(data.replace(/__NONCE__/g, res.locals.nonce));
    });
  });
}

Option B — Skip cache entirely when process.env.NODE_ENV === 'development'.

Affected Files

  • server.js (lines 83-97)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions