Vue3+Vite前端项目部署后部分图片资源无法获取、动态路径图片资源报404错误的原因及解决方案

目录

Vue3+vite前端项目部署后部分图片资源无法获取、动态路径图片资源报404错误的原因及解决方案

一、情景介绍

1、问题出现的场景

2、无法加载的图片写法

二、反向代理原理简介

三、造成该现象的原因

四、解决方案

1、放弃动态渲染

2、在页面挂载的时候引入图片资源

3、修改base路径(最推荐)

五、总结


        作者:watermelo37

        CSDN万粉博主、华为云云享专家、阿里云专家博主、腾讯云、支付宝合作作者,全平台博客昵称watermelo37。

        一个假装是giser的coder,做不只专注于业务逻辑的前端工程师,Java、Docker、Python、LLM均有涉猎。

---------------------------------------------------------------------

温柔地对待温柔的人,包容的三观就是最大的温柔。

---------------------------------------------------------------------

Vue3+vite前端项目部署后部分图片资源无法获取、动态路径图片资源报404错误的原因及解决方案

        本篇博客旨在填补去年遇到的一个技术坑。去年遇到了这个问题只碰巧找到了一种解决方案,并没有确定错误发生的原因,今年更新项目重部署的时候又遇到了该问题,这次成功找到了根本原因,并且找到了多种解决方案,特此分享给大家,没看过去年博文的也没关系,这篇会详细介绍。

        去年的博文重实践(不求甚解,只有一种解决方案),今年的博文重思维(求根问底,不同思路的解决方案)。欢迎读者按需阅读~

        直接获取解决方案请点击:四、解决方案

        去年博文传送门:

开发和内网部署正常,反向代理后出现404和图片加载失败的解决方案;部署到公网后报错404;部署到公网后图片加载出错;动态渲染获取图片失败_访问代理服务器图片加载不出来

一、情景介绍

1、问题出现的场景

        最近开发一个前端项目,在开发环境和部署到内网的生产环境都没问题。将其反向代理到一个公网域名上,发现其他的内容没有问题,唯独部分图片资源无法加载,打开控制台,这部分图片资源请求状态码是404。

        说实话这种情况非常令人迷惑,要是所有图片都无法加载那还好理解,可是我图片统一放在public文件夹,打包后也检查了确实都存在,然后部分图片无法获取,这是为什么呢?

2、无法加载的图片写法

        经过检查,我发现直接写相对路径或者绝对路径都不会丢失图片资源,例如,以下写法都能正常加载图片:

<!-- 图片直接放在组件文件旁边的情况(放在assets文件夹同理) -->
 
<div class="fig-container">
        <img class="fig" src="./chaptersImgs/chapter2Fig1.png" alt="" />
        <p class="figTitle" align="center">图2 指标体系构建思路图</p>
</div>
 
 
 
<!-- 图片放在public文件夹中的情况 -->
<img
    src="/dataCenterLogo.png"
    style="
        height: 5.5vh;
        width: auto;
        margin-right: 0.7vw;
          "
/>

        然而,只有v-for或者其他变量生成的动态路径,在反向代理后无法加载。要知道在开发环境和内网生产环境都没有问题,却在反向代理之后出错了,这是为什么呢?

        举个会出错的例子:

      <!-- 使用v-for动态渲染模块,并填充图片,动态生成图片路径的方式 -->
      <el-row class="row" :gutter="0">
        <el-col
          v-for="(item, i) in urlReport"
          :span="6"
          class="chapter-col"
          justify="center"
          :key="i"
        >
          <div class="singleDownload" @click="downloadByUrl(item.url)">
            <div class="card-image-container">
              <img :src="'/download/report' + ( i + 1 ) + '.png'" class="card-image" />
            </div>
            <div class="description">
              {{ item.reportName }}
            </div>
          </div>
        </el-col>
      </el-row>

二、反向代理原理简介

        反向代理的基本原理是,客户端的请求先发送到代理服务器,代理服务器再将请求转发给真实的后端服务。比如我将一个项目只部署到一个内网服务器上,同时反向代理到一个可公开访问的代理服务器上,这样用户只需要访问这个代理服务器,代理服务器就会将请求发送到内网的真实服务器上并获取相应资源。这样可以避免用户直接接触真实服务器。同时也可以通过一个域名挂载多个前端项目。

        在前端项目中,反向代理通常用于跨域请求、资源代理等场景。当反向代理配置不当时,可能导致一些资源的路径错误,进而导致资源加载失败。

三、造成该现象的原因

        问题的根源在于 Vite 的动态路径解析方式。在开发环境中,Vite 会根据根路径(base)自动解析资源路径,但当通过反向代理部署时,代理服务器可能会为项目添加一个子路由路径(根据nginx的配置来决定)。这个路径的变化影响了 Vite 对资源路径的解析,导致动态生成的路径与实际资源路径不一致,因此找不到对应的图片资源。

        具体来说,当我们使用动态路径时,Vite 默认将其视为相对于项目根路径来解析,但当反向代理添加了子路由路径后,动态路径没有考虑到这个变化,最终导致图片无法加载。

         以这个nginx配置为例,部署之后拼接的资源动态路径就是“域名+high+动态路由”,可如果你的项目base目录是默认值或者“./”,那资源的实际路径其实是“域名+动态路由”,自然就会报404错误。

server {
    listen 8001;
    server_name xxx.xx.xxx.xx;

    location /high/{
        alias E:/deploy/developmentV2.0-update2024report/; 
        try_files $uri $uri/ /project1/index.html;
    }
}

四、解决方案

        为了解决这个问题,本文提供了三种不同思路的解决方案。欢迎大家根据自己的需求选择合适的方案,也欢迎在评论区分享其他解决思路。

1、放弃动态渲染

        这个方案的思路比较简单:如果动态渲染无法正常加载图片,那么就放弃动态渲染,改为静态引用。属于是“解决不了问题,就解决产生问题的对象”。但它不适用于需要大量渲染、图片较多的场景,因此不具备长效解决问题的作用。

2、在页面挂载的时候引入图片资源

        动态路径是在运行时才解析并加载图片资源。我们可以通过import提前加载图片并将其存储到数组中。这样,动态渲染时只需要从已加载的图片数组中获取资源,避免了路径解析的问题。具体实现如下:

      <el-row class="row" :gutter="0">
        <el-col
          v-for="(item, i) in urlReport"
          :span="6"
          class="chapter-col"
          justify="center"
          :key="i"
        >
          <div class="singleDownload" @click="downloadByUrl(item.url)">
            <div class="card-image-container">
              <img :src="reportPic[i]" class="card-image" />
            </div>
            <div class="description">
              {{ item.reportName }}
            </div>
          </div>
        </el-col>
      </el-row>

 
// 图片存放路径
const webPic = ref([]);
const reportPic = ref([]);
 
 
// 异步加载图片
Promise.all([import("/download/web1.png"), import("/download/web2.png")]).then(
  (images) => {
    webPic.value = images.map((image) => image.default);
  }
);
Promise.all([
  import("/download/report1.png"),
  import("/download/report2.png"),
  import("/download/report3.png"),
  import("/download/report4.png"),
  import("/download/report5.png"),
  import("/download/report6.png"),
  import("/download/report7.png"),
  // import("/download/report8.png"),
  import("/download/report9.png"),
  import("/download/report10.png"),
  import("/download/report11.png"),
  import("/download/report12.png"),
  import("/download/report13.png"),
]).then((images) => {
  reportPic.value = images.map((image) => image.default);
});

        在构建时,Vite 会处理这些图片资源,并将其打包到最终的构建目录中。import 会返回一个模块对象,其中 default 属性包含了图片的实际路径,所以不受base路径变化的影响。

        简单点说,不管你的开发环境base路径是什么,生产环境base路径是什么,你都可以用这种方法批量获得路径。

3、修改base路径(最推荐)

        既然我们已经知道了问题的原因,最直接的解决办法是修改 Vite 的 base 路径,使其与反向代理的实际路径匹配。你可以还是按照原来的写法:

      <!-- 使用v-for动态渲染模块,并填充图片,动态生成图片路径的方式 -->
      <el-row class="row" :gutter="0">
        <el-col
          v-for="(item, i) in urlReport"
          :span="6"
          class="chapter-col"
          justify="center"
          :key="i"
        >
          <div class="singleDownload" @click="downloadByUrl(item.url)">
            <div class="card-image-container">
              <img :src="'/download/report' + ( i + 1 ) + '.png'" class="card-image" />
            </div>
            <div class="description">
              {{ item.reportName }}
            </div>
          </div>
        </el-col>
      </el-row>

        然后在 vite.config.js 中配置 base 选项:

export default defineConfig({
    base: '/你的子路径/'
});

        这里的子路径是由反向代理的路由决定的。比如你的域名是www.jd.com,你将项目反向代理到www.jd.com/newProject上,那么base的值就是"/newProject/"。这里其实就是老生常谈的“开发环境应与生产环境一致”的体现

五、总结

        回头来看,这其实是一个很简单的问题,只需要遵守开发环境应与生产环境一致的原则就好了,可是在我真正做一次部署之前是没法深刻理解这句话的含义的,不吃一堑就是不长一智,那能怎么办呢?去年我甚至都没意识到根本问题出在哪,只是找到了一种解决方案(上述第二种)。希望我这篇博客能帮助大家理解这句话,或者在犯了错的时候找到解决方案。

        本篇博文详细分析了 Vue3 + Vite 前端项目在反向代理部署后,部分图片(动态路径图片)无法加载的问题。通过分析问题的原因,并结合三种解决方案(放弃动态渲染、提前引入图片资源、修改 base 路径),我们可以有效地解决这一问题。希望本篇文章能为大家解决类似问题提供帮助。

        只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

        其他热门文章,请关注:

        极致的灵活度满足工程美学:用Vue Flow绘制一个完美流程图

        你真的会使用Vue3的onMounted钩子函数吗?Vue3中onMounted的用法详解

        通过array.filter()实现数组的数据筛选、数据清洗和链式调用

        通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能

        通过MongoDB Atlas 实现语义搜索与 RAG——迈向AI的搜索机制

        TreeSize:免费的磁盘清理与管理神器,解决C盘爆满的燃眉之急

        深入理解 JavaScript 中的 Array.find() 方法:原理、性能优势与实用案例详解

        el-table实现动态数据的实时排序,一篇文章讲清楚elementui的表格排序功能

        MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver

        Dockerfile全面指南:从基础到进阶,掌握容器化构建的核心工具

        在线编程实现!如何在Java后端通过DockerClient操作Docker生成python环境

        干货含源码!如何用Java后端操作Docker(命令行篇)

<think>嗯,用户问的是Vue3+Vite打包之后出现白屏的问题。我得先想想可能的原因有哪些。首先,白屏通常是因为资源载失败或者JavaScript执行错误Vue3Vite项目在打包后可能遇到的问题有哪些呢? 首先,路径配置问题。Vite默认的base路径是根目录,但如果项目部署在子目录下,可能需要修改base配置。如果没设置正确,打包后的资源路径可能出错,导致JS和CSS载失败,页面空白。 然后是路由模式的问题。Vue Router如果用了history模式,而服务器没有正确配置,比如没有处理404的情况,可能会导致刷新页面时白屏。这时候可能需要服务器配置回退到index.html,或者改用hash模式。 还有可能是代码分割或异步载的问题。Vite默认使用动态import,如果组件载失败,比如路径错误或组件未正确导出,可能导致整个应用挂掉。这时候需要检查路由配置和组件导入是否正确。 浏览器兼容性也是一个因素。Vite默认的构建目标可能不支持旧版浏览器,如果用户的浏览器太老,可能无法运行ES6+的代码,导致白屏。可能需要调整build.target设置或引入polyfill。 资源文件引用错误,比如图片或静态资源路径不对,虽然这通常不会导致整个应用白屏,但如果有关键资源载失败,也可能影响渲染。 还有可能打包后的文件存在语法错误,比如未正确处理环境变量,或者某些代码在生产环境下错。这时候需要检查控制台错误,看看是否有JS执行错误。 另外,Vite的插件兼容性问题也可能导致打包后的文件有问题,比如某些插件在生产环境下行为不一致,需要检查插件配置和版本是否兼容Vite的版本。 用户可能需要逐步排查这些可能性。首先检查浏览器控制台的错信息,看是否有资源载失败或JS错误。然后根据错误信息定位问题,比如路径问题、路由配置、浏览器兼容性等。如果是路由问题,可以尝试改为hash模式测试;如果是路径问题,检查base配置和资源引用路径;如果是兼容性问题,调整构建目标或添polyfill。 可能还需要建议用户部署到服务器后,检查服务器配置是否正确,比如是否启用了gzip压缩、是否正确设置了MIME类型,或者是否需要配置重写规则来处理前端路由。 总结来说,解决白屏问题需要从资源路径、路由配置、服务器设置、浏览器兼容性、代码错误等多个方面进行排查,逐步缩小问题范围,找到具体原因后再进行相应的调整和修复。</think>以下是 Vue3 + Vite 项目打包后出现白屏问题的排查思路和解决方案(请按顺序逐步排查): --- ### 一、基础路径配置问题(最常见原因) **现象**:控制台提示 `Failed to load resource` 错误 ```javascript // vite.config.js export default defineConfig({ base: &#39;/your-sub-path/&#39;, // 若部署在根目录则保持默认 &#39;/&#39; build: { outDir: &#39;dist&#39; } }) ``` **解决方法**: 1. 确认部署服务器的实际路径 2. 修改 `vite.config.js` 中的 `base` 配置 3. 重新打包部署 --- ### 二、路由模式问题(history vs hash) **现象**:首页可访问,但刷新子路由出现白屏 ```javascript // router/index.js const router = createRouter({ history: createWebHistory(), // 改为 createWebHashHistory() 测试 routes }) ``` **解决方法**: 1. 临时改用 hash 模式测试 2. 生产环境若需保持 history 模式: - Nginx 需添 `try_files $uri $uri/ /index.html` - Apache 需配置 `.htaccess` 重定向规则 --- ### 三、异步组件载失败 **现象**:控制台显示 `ChunkLoadError` ```javascript // 检查动态导入语法是否正确 const UserDetails = defineAsyncComponent(() => import(&#39;./views/UserDetails.vue&#39;) ) ``` **解决方法**: 1. 检查组件路径是否正确 2. 确认组件导出是否规范 3. 使用 `vite-plugin-inspect` 分析打包结果 --- ### 四、浏览器兼容性问题 **现象**:旧版浏览器无法运行 ```javascript // vite.config.js export default defineConfig({ build: { target: [&#39;es2015&#39;] // 可调整为更兼容的版本 } }) ``` **补充方案**: 1. 安装 `@vitejs/plugin-legacy` 2.浏览器 polyfill --- ### 五、静态资源路径问题 **现象**:图片/CSS等资源载失败 ```html <!-- 错误写法 --> <img src="./assets/logo.png"> <!-- 正确写法 --> <img src="/assets/logo.png"> 或 <img :src="new URL(&#39;./assets/logo.png&#39;, import.meta.url).href"> ``` --- ### 六、生产环境特定错误 **排查步骤**: 1. 本地预览打包结果: ```bash npm run build npm run preview ``` 2. 检查浏览器控制台错误信息 3. 对比开发/生产环境配置差异 4. 检查环境变量使用: ```javascript if (import.meta.env.PROD) { // 生产环境特定逻辑 } ``` --- ### 七、服务器配置示例(Nginx) ```nginx server { listen 80; server_name your-domain.com; location / { root /path/to/dist; index index.html; try_files $uri $uri/ /index.html; # 关键配置 } # 启用gzip gzip on; gzip_types text/plain application/javascript text/css; } ``` --- ### 八、高级排查工具 1. 使用 `console.log` 在入口文件定位执行点 2.全局错误捕获: ```javascript // main.js app.config.errorHandler = (err) => { console.error(&#39;Vue Error:&#39;, err) } ``` 3. 分析打包产物: ```bash npx vite-bundle-visualizer ``` --- **推荐排查顺序**: 1. 通过 `npm run preview` 本地验证 2. 检查浏览器控制台错误 3. 核对路由模式和服务器配置 4. 验证静态资源路径 5. 检查浏览器兼容性 按照这个流程排查,90%以上的白屏问题都能找到解决方案。如果问题仍未解决,可以提供具体的错误日志以便进一步分析。
评论 113
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值