Skip to content

解决前端打包直接访问index.html发生的跨域报错

有的时候,项目打包后不想启用服务,又想直接本地访问打包后的index.html项目。

1.报错详情:

js
index.html:1  Access to script at 'file:///D:/codes/web-react/dist/assets/index-CxPD88b2.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: chrome-extension, chrome-untrusted, data, edge, http, https, isolated-app.
index-CxPD88b2.js:1 
        Failed to load resource: net::ERR_FAILED
index.html:1  Access to CSS stylesheet at 'file:///D:/codes/web-react/dist/assets/index-Bf4PHeBe.css' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: chrome-extension, chrome-untrusted, data, edge, http, https, isolated-app.

2. dist文件

index.html 内容

html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>X6 Flow Editor</title>
    <script type="module" crossorigin src="./assets/index-CxPD88b2.js"></script>
    <link rel="stylesheet" crossorigin href="./assets/index-Bf4PHeBe.css">
  </head>
  <body>
    <div id="root"></div>

  </body>
</html>

3.错误原因

  现代浏览器使用 ES 模块(ESM)加载 JavaScript 文件。ESM 要求 JavaScript 文件使用正确的协议(如 http 或 https),而不能使用 file:// 协议。

  而这段代码使用了 file协议: <script type="module" crossorigin src="./assets/index-CxPD88b2.js"></script>,当直接打开 index.html 文件时,使用的是 file:// 协议,这会导致:现代浏览器因为安全策略,限制了 file:// 协议下的 ESM 加载, 出现 CORS(跨域资源共享)错误 。

  就是说现代的浏览器为了安全性,禁止了file协议的使用,所以访问直接打包后的项目会报错。

解决办法

  这里使用vite工具通过配置@vitejs/plugin-legacy插件,自动处理模块加载的兼容性问题,避免了 file:// 协议下的 CORS 问题。

@vitejs/plugin-legacy 插件的作用

生成两个版本的代码:一个现代版本和一个兼容版本
使用传统的脚本加载方式(而不是 ESM)
自动处理模块加载的兼容性问题
避免了 file:// 协议下的 CORS 问题

安装

js
pnpm install @vitejs/plugin-legacy

使用

创建一个 legacy.ts 文件:

js

import legacy from '@vitejs/plugin-legacy';
export default legacy({
    targets: ['ie>=11'],
    additionalLegacyPolyfills: ['regenerator-runtime/runtime'],
});

在 vite.config.ts 文件中引入:

js
import { defineConfig } from "vite";
import * as path from "path";
import  legacy  from "./plugins/legacy";
export default defineConfig({
  base:'./',
  plugins:legacy,
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
  server: {
    host: "0.0.0.0", //ip地址
    port: 8086, // 设置服务启动端口号
  },
});

使用 @vitejs/plugin-legacy 打包之后的index.html文件:

js
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>X6 Flow Editor</title>
    <script type="module" crossorigin src="./assets/index-CTxLVFoW.js"></script>
    <link rel="stylesheet" crossorigin href="./assets/index-BJhNsWlE.css">
    <script type="module">import.meta.url;import("_").catch(()=>1);(async function*(){})().next();if(location.protocol!="file:"){window.__vite_is_modern_browser=true}</script>
    <script type="module">!function(){if(window.__vite_is_modern_browser)return;console.warn("vite: loading legacy chunks, syntax error above and the same error below should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}();</script>
  </head>
  <body>
    <div id="root"></div>
    <script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
    <script nomodule crossorigin id="vite-legacy-polyfill" src="./assets/polyfills-legacy-ByMQLnbB.js"></script>
    <script nomodule crossorigin id="vite-legacy-entry" data-src="./assets/index-legacy-BptH6DBt.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
  </body>
</html>

源码

https://github.com/zhulongxu/web-react

用心写代码,用心写文章