使用 vite 构建的项目打包后直接使用浏览器打开index.html文件显示一片空白

1,501 阅读2分钟

一、浏览器直接打开显示空白原因排查(重点看第二个的解决方案)

  • 相对路径资源加载问题

    浏览器在直接打开文件时,使用的是 file:// 协议,这会导致相对路径解析与服务器环境(如 Live Server 使用的 http:// 协议)不同。比如: html预览

    <!-- 文件结构 -->
    project/
      ├── index.html
      └── css/
           └── style.css
    
    <!-- index.html 中的引用 -->
    <link rel="stylesheet" href="css/style.css">
    

    直接用浏览器打开时,路径会被解析为 file:///path/to/project/css/style.css,可能因为路径格式或权限问题导致加载失败。而 Live Server 作为服务器,会正确处理相对路径。

  • JavaScript 模块导入限制

    ES6 模块的导入(如 import 语句)在 file:// 协议下有安全限制:

    
    // 第一种script.js 
    import { someFunction } from './module.js';
    // 第二种index.html(大多数为第二种形式)
    <!DOCTYPE html>
    <html>
    <head>
      <script type="module" crossorigin src="/js/index-ef68378e.js"></script>
    </head>
    <body>
      <div id="app">
    </body>
    </html>
    

    直接打开 HTML 文件时,浏览器会阻止此类跨文件模块加载,导致 JavaScript 无法正常运行。vscode的 Live Server 则允许这种导入。

  • CORS(跨域资源共享)问题

    如果页面尝试加载其他域的资源(如 API 请求),file:// 协议会触发更严格的安全策略,而 Live Server 作为本地服务器不会有此限制。

  • 服务器端特性依赖

    如果 HTML 页面依赖服务器端功能(如 PHP、Node.js 处理),直接用浏览器打开显然无法正常工作,因为没有服务器处理这些请求。

二、解决方案

  • 使用相对路径时:确保路径正确,避免使用绝对路径或相对于根目录的路径。

  • JavaScript 模块:如果使用了 ES6 模块,建议始终通过服务器环境打开。或者使用 @vitejs/plugin-legacy插件如下:

    // vite.config.js 配置 base: “./” (在webpack中则配置publicPath: "./"即可)
    // 安装 npm install @vitejs/plugin-legacy
    // vite.config.js
    import legacy from '@vitejs/plugin-legacy';
    export default defineConfig({
      base: './', // 关键配置,确保资源路径为相对路径
      plugins: [
        legacy({
          targets: ['ie >= 11'], // 或其他需要支持的浏览器
          additionalLegacyPolyfills: ['regenerator-runtime/runtime'],
        }),
        vue(),
      ],
      build: {
        target: ['es2015', 'chrome63'], // 默认是modules,百度说是更改这个会去输出兼容浏览器,尝试没啥作用,先配置吧
      }
    })
    
    //在dist并列的文件夹中创建脚本文件 (用于替换module等关键词,省的每次得手动删除)`toFile.mjs`创建 toFiles.mjs (为啥格式不是js为了执行命令不报兼容的错误)
    import fs from 'fs'
    console.time('转换耗时')
    const distPath = './dist/index.html' //打包路径的index.html
    let htmlText = fs.readFileSync(distPath, 'utf8')
    let resultText = ''
    let htmlArr = htmlText.match(/.*\n/g) || []
    htmlArr.forEach((str) => {
      str = str.replace(/\s?nomodule\s?/g, ' ')
      str = str.replace(/\s?crossorigin\s?/g, ' ')
      str = str.replace(/data-src/g, 'src')
      if (!/type="module"/i.test(str)) resultText += str
    })
    fs.writeFileSync(distPath, resultText, 'utf8')
    console.timeEnd('转换耗时')
    

    image.png

    // package.json命令改为:
    "build": "vite build && node toFile.mjs",
    // npm run build 之后打开index.html文件
    
  • 调试技巧:在浏览器开发者工具的控制台查看错误信息,常见错误如 Failed to load resource 或 Cross origin requests are only supported for protocol schemes

  • 使用本地服务器:除了 Live Server,还可以使用 Python 的 http.server 模块:

    # 在项目目录下运行
    python -m http.server 8000