CORS 错误。无法从 index.html 访问父目录中的资产文件夹

CORS Error. cannot access assets folder in parent directory from index.html

我正在学习 JavaScript Morten Rand-Hendriksen 的课程(JavaScript 基本培训)。我在本地下载了所有练习文件并使用 Firefox 和 VSCode 以及 Live Server 运行,我尝试在浏览器中加载下面的示例代码(示例 5.02)。

不显示背包图片的CSS样式。在控制台中,我收到此错误:

The resource from “http://127.0.0.1:5500/assets/style.css” was blocked due to MIME type (“text/html”) mismatch (X-Content-Type-Options: nosniff).

我在“设置”中将“跟踪内容”设置为“关闭”(见屏幕截图),但没有帮助。

我确认文件存在“..\assets\images\everyday.svg”

Update: 我尝试直接在 Firefox 中加载它,而不是 LiveServer。我在控制台中看到,跨源请求被阻止:同源策略不允许读取位于 file:///C:/Users/Me/Documents/Learn/JS/05_03/Backpack.js 的远程资源。 (原因:CORS 请求不是 http)。

实际结果

预期结果:

代码在这里:

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>BackpackPacker</title>
    <link
      href="https://fonts.googleapis.com/css2?family=Oswald:wght@200..700&family=Work+Sans:wght@100..900&display=swap"
      rel="stylesheet"
    />
    <link
      rel="stylesheet"
      href="../assets/style.css"
      type="text/css"
      media="all"
    />
    <script type="module" src="Backpack.js"></script>
    <script type="module" src="script.js"></script>
  </head>
  <body>
    <header class="siteheader">
      <div class="site-title">BackpackPacker</div>
      <div class="site-description">All backpack packing, all the time.</div>
    </header>
    <main class="maincontent"></main>
    <footer class="sitefooter">
      <p>
        Demo project for JavaScript Essential Training, a LinkedIn Learning
        course.
      </p>
    </footer>
  </body>
</html>

Backpack.js

class Backpack {
  constructor(
    name,
    volume,
    color,
    pocketNum,
    strapLengthL,
    strapLengthR,
    lidOpen,
    dateAcquired,
    image
  ) {
    this.name = name;
    this.volume = volume;
    this.color = color;
    this.pocketNum = pocketNum;
    this.strapLength = {
      left: strapLengthL,
      right: strapLengthR,
    };
    this.lidOpen = lidOpen;
    this.dateAcquired = dateAcquired;
    this.image = image;
  }
  toggleLid(lidStatus) {
    this.lidOpen = lidStatus;
  }
  newStrapLength(lengthLeft, lengthRight) {
    this.strapLength.left = lengthLeft;
    this.strapLength.right = lengthRight;
  }
  backpackAge() {
    let now = new Date();
    let acquired = new Date(this.dateAcquired);
    let elapsed = now - acquired; // elapsed time in milliseconds
    let daysSinceAcquired = Math.floor(elapsed / (1000 * 3600 * 24));
    return daysSinceAcquired;
  }
}

export default Backpack;

script.js

/**
 * Traverse the DOM tree using querySelector() and querySelectorAll()
 * @link https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector
 * @link https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll
 */

import Backpack from "./Backpack.js";

const everydayPack = new Backpack(
  "Everyday Backpack",
  30,
  "grey",
  15,
  26,
  26,
  false,
  "December 5, 2018 15:00:00 PST",
  "../assets/images/everyday.svg"
);

const main = document.querySelector(".maincontent");

const content = `
  <article class="backpack" id="everyday">
    <figure class="backpack__image">
      <img src=${everydayPack.image} alt="" />
    </figure>
    <h1 class="backpack__name">${everydayPack.name}</h1>
    <ul class="backpack__features">
      <li class="backpack__volume">Volume:<span> ${
        everydayPack.volume
      }l</span></li>
      <li class="backpack__color">Color:<span> ${everydayPack.color}</span></li>
      <li class="backpack__age">Age:<span> ${everydayPack.backpackAge()} days old</span></li>
      <li class="backpack__pockets">Number of pockets:<span> ${
        everydayPack.pocketNum
      }</span></li>
      <li class="backpack__strap">Left strap length:<span> ${
        everydayPack.strapLength.left
      } inches</span></li>
      <li class="backpack__strap">Right strap length:<span> ${
        everydayPack.strapLength.right
      } inches</span></li>
      <li class="backpack__lid">Lid status:<span> ${
        everydayPack.lidOpen
      }</span></li>
    </ul>
  </article>
`;

main.innerHTML = content;

CSS 文件在../assets/style.css

body {
  margin: 0;
  font-family: "Work Sans", sans-serif;
  font-size: 1.6rem;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: "Oswald", sans-serif;
}

figure {
  margin: 0;
}

.siteheader {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 2rem;
}

.site-title {
  margin-top: 1rem;
  margin-bottom: 1rem;
  font-family: "Oswald", sans-serif;
  font-size: 5rem;
  font-weight: 200;
}

.siteheader:after {
  display: block;
  margin: 4rem 0;
  content: "⚍⚌⚍";
}

.maincontent {
  margin: 0 auto;
  padding: 0 1rem;
  max-width: 60rem;
}

.page-header {
  margin-bottom: 3rem;
}

.page-header__heading {
  margin-top: -1rem;
  text-align: center;
}

.page-header:after {
  margin: 4rem auto;
  display: block;
  content: "";
  border-bottom: 3px solid black;
  width: 4rem;
}

.backpack {
  margin-bottom: 4rem;
  /* padding-bottom: rem; */
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: auto 1fr;
  gap: 0 3rem;
}

.backpack:after {
  margin: 0 auto;
  padding-top: 4rem;
  display: block;
  grid-column: span 2;
  content: "";
  border-bottom: 3px solid black;
  width: 4rem;
}

.backpack__image {
  grid-row: span 2;
}

.backpack__name {
  margin-top: 2rem;
  margin-bottom: 0;
  padding-bottom: 2rem;
  font-size: 5rem;
  line-height: 1;
  text-transform: uppercase;
  border-bottom: 3px solid black;
}

.backpack__features {
  margin: 0;
  padding: 2rem 0 0 0;
  list-style-type: none;
}

.backpack__features li {
  padding: 0.2rem 0;
}

/* Subgrid. See https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Subgrid */
@supports (grid-template-columns: subgrid) {
  .backpack__features {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0 1rem;
  }

  .backpack__features li {
    display: grid;
    grid-column: span 2;
    grid-template-columns: subgrid;
  }
}

.lid-toggle {
  display: inline-block;
  border: 3px solid black;
  border-radius: 0.3rem;
  padding: 2rem;
  font-size: 1.6rem;
  cursor: pointer;
  background-color: white;
}
.lid-toggle:hover,
.lid-toggle:focus {
  background-color: hsl(0, 0%, 95%);
}

.lid-toggle:active {
  background-color: black;
  color: white;
}

.sitefooter {
  margin-top: 8rem;
  padding: 2rem;
  display: flex;
  justify-content: center;
  background: black;
  color: white;
}

如果您收到 CORS 错误,并且您正在本地访问您的站点(通过文件系统或 Live Server),此错误通常意味着您的 href 路径有问题,src 路径,或与您的文件层次结构。 如果您使用的是节点服务器,那么这个答案可能不适合您。

文件系统和 Live Server 处理父目录的方式不同。

Live Server 使用您打开的文件夹(在 VS Code 中)作为根目录,并且不会让您转到上面的父目录。

假设您在 VS Code 中打开的文件夹仅包含您的 index.html 文件,而您的资产文件夹位于其父目录中。

在这种情况下,Live Server 将不允许您访问资产文件夹中的文件。

通常,../ 会将您带到父目录,但在 Live Server 中,如果您已经设置在 'root' 目录(在 VS Code 中打开的文件夹)中,则 ../不会带你去任何地方。

这与您的本地文件系统不同,在本地文件系统中,../ 将根据您的意愿进入尽可能多的父目录,直到到达根驱动器。

我的建议是:

使您的文件层次结构尽可能简单。

将 index.html 放在项目的根文件夹中,然后将资产保存在子文件夹中,而不是父目录中。

  • 项目文件夹

包含 index.html 和您的资产文件夹

  • 资产文件夹

包含 script.js 和 style.css

然后,在您的 html 文件中,将您的路径更改为 assets/style.cssassets/script.js

这将使您的站点同时适用于 Live Server 和本地文件系统。在线部署您的网站时,它也会使事情变得更容易。

编辑: 你在 VS Code 中打开的任何文件夹都将是你的根目录,Live Server 将允许你从那里和所有子目录访问文件。如果无法将资产移动到项目目录,请确保在 VS Code 中打开包含资产文件夹的文件夹。然后导航到您的 html 文件并从那里启动 Live Server。

注意:请参阅最后的替代解决方案。

经过大量搜索,我发现这是 LiveServer 的 VSCode 功能。 在包含子文件夹的 JS 文件夹中,我看到有一个 .vscode 文件夹,其中包含一个文件 settings.json。 在文件中,我添加了根位置行。 所以我的设置文件看起来像这样。

settings.json

{
    "editor.formatOnSave": true,
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "liveServer.settings.root": "./"
}

在 VSCode 中,在文件菜单下,我选择了“将文件夹添加到工作区”并添加了 JS 文件夹

现在,当我打开 VSCode 时,我单击通常用于“复制”的选择不当的图标,它会打开 VSCode 资源管理器。

所以我现在要做的就是在任何子文件夹中打开 index.html 然后右键单击并选择 “在 LiveServer 中打开”

备选方案:

  1. 在 VSCode 中选择文件菜单中的打开文件夹

  1. 在VSCode右下角(假设安装了Live Server扩展),点击“上线”。

  1. 您将看到目录列表;现在您可以进入子文件夹并打开其 index.html

您会发现资产自动可用。