code: async function handleGenericFile(req, res, fileExtension) {
      const nodeFilePath = `.${req.url}`;
  
      // check if the file is in the cache
      if (compiledFiles[nodeFilePath]) {
          res.end(compiledFiles[nodeFilePath]);
          return;
      }
  
      // the file is not in the cache
      // watch the file if necessary
      // compile the file and return the compiled source
      if (await fs.exists(nodeFilePath)) {
          watchFile(nodeFilePath, watchFiles);
          const source = await fs.readFile(nodeFilePath);
          compiledFiles[nodeFilePath] = source;
          res.end(source);
          return;
      }
  
      //TODO this code is repeated multiple times
      // if SPA is enabled, return the contents to index.html
      // if SPA is not enabled, return a 404 error
      if (!disableSpa) {
          const indexFileContents = (await fs.readFile(`./index.html`)).toString();
          const modifiedIndexFileContents = modifyHTML(indexFileContents, 'index.html', watchFiles, webSocketPort);
          const directoryPath = req.url.slice(0, req.url.lastIndexOf('/')) || '/';
          res.end(modifyHTML(modifiedIndexFileContents, directoryPath, watchFiles, webSocketPort));
          return;
      }
      else {
          res.statusCode = 404;
          res.end();
          return;
      }
  }
docs: TODO this code is very similar to handleScriptExtension