I'm a new student to javascript. I have been practicing loading JSON from localhost to a local html file, but seeing CORS errors continuously.
[Issue]: Different CORS error messages on Chrome / Firefox
- Chrome: "Access to XMLHttpRequest at 'file:/// ...(local path)... charStat.json' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https."
- Firefox: "Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at file:/// ...(local path)... charStat.json. (Reason: CORS request not http)."
[What I've tried]
- Set up a simple web server using php + nginx. No domain, just localhost (http://127.0.0.1)
- Locate JSON file under localhost (http://127.0.0.1/charStat.json)
- In Firefox about:config, opt-out "privacy.file_unique_origin" (set to 'false')
battle.html (local file)
  <!DOCTYPE html>
  <html lang="en-US">
  <!-- abbreviated -->
  <body>
    <div id = "charNow">
      <table id= "chardata" border="2">
        <thead>
          <th>Class</th>
          <th>CT</th>
          <th>Level</th>
          <th>HP</th>
          <th>EN</th>
        </thead>
        <tbody>
        </tbody>
      </table>
    </div>
  </body>
  <script src="js/battle.js"></script>
  <script src="js/jquery-3.5.1.js"></script>
  </html>
battle.js (local file)
// abbreviated
const request = new XMLHttpRequest();
const path = 'http://127.0.0.1/charStat.json';
const statTable = function () {
  $.getJSON(`charStat.json`, function(data) {
    $.each(data.statsByClass, function(i, f) {
      let tblRow = "<tr>"
      + "<td>" + f.class + "</td>"
      + "<td>" + f.ct + "</td>"
      + "<td>" + f.statTable[1].level + "</td>"
      + "<td>" + f.statTable[1].hp + "</td>"
      + "<td>" + f.statTable[1].en + "</td>"
      + "</tr>"
      $(tblRow).appendTo("#chardata tbody");
    });
  });
}
function loadJSONFile(file, callback) {
  request.open(`GET`, file, true);
  request.responseType = 'json'; 
  request.onreadystatechange = function() {
    if (request.readyState === 4 && request.status == `200`) {
      callback(request.response);
    }
  }
  request.send(null);
}
loadJSONFile(path, statTable);
charStat.json (under localhost)
{
  "statsByClass" : [
  {
    "class" : "Warrior",
    "ct" : 300,
    "statTable" : [
      { "level" : 0, "hp" : 1000, "en" : 200, "str" : 20, "vit" : 16, "agl" : 10, "spd" : 15, "int" : 8, "xpToNextLv" : 1 },
      { "level" : 1, "hp" : 1200, "en" : 300, "str" : 24, "vit" : 20, "agl" : 12, "spd" : 19, "int" : 9, "xpToNextLv" : 300 },
      { "level" : 2, "hp" : 1400, "en" : 300, "str" : 26, "vit" : 22, "agl" : 13, "spd" : 19, "int" : 9, "xpToNextLv" : 400 },
  // ... abbreviated ...
    ]
  }
]}
 
    