当前位置: 首页 > news >正文

Nginx 配置 Vue 项目 Hash/History 模式路由跳转错误的解决方案

网罗开发(小红书、快手、视频号同名)

  大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。

图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG

我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。

展菲:您的前沿技术领航员
👋 大家好,我是展菲!
📱 全网搜索“展菲”,即可纵览我在各大平台的知识足迹。
📣 公众号“Swift社区”,每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。
💬 微信端添加好友“fzhanfei”,与我直接交流,不管是项目瓶颈的求助,还是行业趋势的探讨,随时畅所欲言。
📅 最新动态:2025 年 3 月 17 日
快来加入技术社区,一起挖掘技术的无限潜能,携手迈向数字化新征程!


文章目录

    • 前言
    • 背景:Nginx 配置 + Vue 路由模式
    • 遇到的问题
    • 问题出在哪里?
    • 如何解决?
      • 方案一:继续使用 Hash 模式(推荐初学者)
      • 方案二:使用 History 模式(推荐最终方案)
    • 实战 Demo 配置(可运行)
    • 总结

前言

最近在一个实际项目中,前端采用 Vue2,路由模式是 hash,后台通过 Nginx 部署。我们遇到一个让人头疼的问题:访问子路径路由 /inv/#/login 时,竟然跳转到了错误的页面。切换成 history 模式后路由倒是正常了,但一刷新页面,前端资源就加载失败,提示 MIME 类型错误。

这篇文章我会把问题的原因分析清楚,然后结合 Nginx 配置与 Vue 路由的特性给出可运行的解决方案,顺便给出实际案例中的 Demo 配置,方便你参考。

背景:Nginx 配置 + Vue 路由模式

在我们的项目中,存在两个前端子系统:

  • 管理端:路径 / → 对应目录 /data/web/sccmp/
  • 组长端:路径 /inv/ → 对应目录 /data/web/inv/

Nginx 配置如下:

location / {alias /data/web/sccmp/;index index.html index.htm;try_files $uri $uri/ /index.html;
}location /inv/ {alias /data/web/inv/;index index.html index.htm;try_files $uri $uri/ /inv/index.html;
}

Vue 项目中,路由配置采用的是 hash 模式:

const router = new VueRouter({mode: 'hash',routes: [{ path: '/login', component: Login },{ path: '/dashboard', component: Dashboard }]
})

遇到的问题

  1. 在 hash 模式下访问组长端 https://xxxx.xx.cppinfo.cn/inv/#/login
    页面居然跳转到管理端的登录页,而不是组长端。

  2. 在 history 模式下刷新页面
    出现错误:

    Failed to load module script: Expected a JavaScript-or-Wasm module script 
    but the server responded with a MIME type of "text/html".
    

    简单说就是 JS 资源请求到了 HTML 文件,Nginx 没有正确返回对应的静态资源。

问题出在哪里?

这个问题本质上分两层:

  1. Hash 模式下路径混淆
    Hash 模式的 URL 是 https://domain/inv/#/login,实际上 Nginx 并不知道 #/login 部分,它只处理 /inv/,而 Vue 的 JS 脚本却从 / 路径下去加载资源,导致加载的是管理端的 index.html。

  2. History 模式下资源路径错误
    在 history 模式下,Vue 的 URL 例如 /inv/login,Nginx 需要把所有未知路径回退到 /inv/index.html。如果配置不对,就会把资源请求(比如 /inv/js/app.js)错误地 fallback 到 HTML,从而导致 MIME type 错误。

如何解决?

方案一:继续使用 Hash 模式(推荐初学者)

如果项目允许继续用 hash 模式,需要确保 每个子系统的资源路径是独立的,避免加载错目录。

在 Vue 的 vue.config.js 中设置 publicPath

// vue.config.js
module.exports = {publicPath: '/inv/',  // 对应组长端的部署路径outputDir: 'dist',productionSourceMap: false
}

这样构建出来的资源都会挂在 /inv/ 下,避免冲突。

Nginx 保持原配置即可。

方案二:使用 History 模式(推荐最终方案)

History 模式对 URL 更友好,但需要 Nginx 配置精确区分资源和路由。

Nginx 修改如下:

location / {root /data/web/sccmp;index index.html;try_files $uri $uri/ /index.html;
}location /inv/ {root /data/web/inv;index index.html;# 只针对 html 路由回退try_files $uri $uri/ /index.html;
}

关键点:

  • root 用而不是 alias(如果用 alias,要小心路径拼接规则)。
  • try_files/index.html 会 fallback 到当前 root 的 index.html,而不会错误地去加载 / 下的文件。
  • 保证静态资源路径正确,例如 /inv/js/app.js 请求到 /data/web/inv/js/app.js

实战 Demo 配置(可运行)

假设我们有两个 Vue 项目,构建产物分别在 /data/web/sccmp//data/web/inv/

Vue 配置 vue.config.js

// 管理端 vue.config.js
module.exports = {publicPath: '/',outputDir: 'dist-admin',
}// 组长端 vue.config.js
module.exports = {publicPath: '/inv/',outputDir: 'dist-inv',
}

Nginx 配置:

server {listen 80;server_name demo.local;location / {root /data/web/sccmp;index index.html;try_files $uri $uri/ /index.html;}location /inv/ {root /data/web/inv;index index.html;try_files $uri $uri/ /index.html;}
}

这样:

  • 访问 http://demo.local/ → 管理端
  • 访问 http://demo.local/inv/ → 组长端
  • 刷新任意路由(无论是 /dashboard 还是 /inv/login)都能正常返回对应的 index.html,再由前端接管路由。

总结

  • Hash 模式:简单,兼容性强,但 URL 不够美观。需要在 Vue 构建配置里设置好 publicPath,避免资源路径错乱。
  • History 模式:更优雅,但 Nginx 必须配合 try_files 做路由回退,确保静态资源不会被错误地 fallback 到 index.html。
  • 问题本质:不是 Vue 路由写错,而是 Nginx 路径处理和前端 publicPath 没有对应上。

我的建议是:开发初期可以用 Hash 模式省心,上线前建议切换到 History 模式,并仔细配置好 Nginx。


文章转载自:

http://PY5qLny6.fgxnb.cn
http://AHU80X8E.fgxnb.cn
http://DSnx6mbe.fgxnb.cn
http://ePl2PgM2.fgxnb.cn
http://qg8RmtIX.fgxnb.cn
http://mcXjJAKh.fgxnb.cn
http://rDu7yqMu.fgxnb.cn
http://Qa72ihRq.fgxnb.cn
http://pbUzwm46.fgxnb.cn
http://vdyD3ROJ.fgxnb.cn
http://TWuz0JGo.fgxnb.cn
http://MQH3O16X.fgxnb.cn
http://OZmc9ZEl.fgxnb.cn
http://MBKNMfyb.fgxnb.cn
http://ipqpsZlx.fgxnb.cn
http://Fmf8XPts.fgxnb.cn
http://fjUAmZrx.fgxnb.cn
http://ptje2pkT.fgxnb.cn
http://BijvtrQq.fgxnb.cn
http://Dq7CzAFz.fgxnb.cn
http://WOoaKWm7.fgxnb.cn
http://NLeqC87B.fgxnb.cn
http://QKo8YTsq.fgxnb.cn
http://5LbKpuXX.fgxnb.cn
http://jz454He4.fgxnb.cn
http://AXwaKIFg.fgxnb.cn
http://orWlAxey.fgxnb.cn
http://CbaMH4ra.fgxnb.cn
http://rcYsp9gM.fgxnb.cn
http://Sas213Cu.fgxnb.cn
http://www.dtcms.com/a/387116.html

相关文章:

  • Linux Makefile与进度条
  • 硬件驱动——I.MX6ULL裸机启动(3)(按键设置及中断设置
  • 深度学习基本模块:RNN 循环神经网络
  • 【深度学习】PixelShuffle处理操作
  • 10.1 - 遗传算法(旅行商问题C#求解)
  • Java 集合入门:从基础到实战的完整知识指南
  • 《过山车大亨3 完整版》PSXbox版下月推出 预告片赏
  • P1107题解
  • 多目标数据关联算法MATLAB实现
  • 战略推理AI Agents:组装LLM+因果推断+SHAP
  • 【CVPR 2016】基于高效亚像素卷积神经网络的实时单幅图像与视频超分辨率
  • 基于STM32的LED实战 -- 流水灯、呼吸灯、流水呼吸灯
  • 【数据结构】——队列,栈(基于链表或数组实现)
  • 任天堂官网更新!“任亏券”不支持兑换NS2专用游戏
  • 大模型数据整理器打包及填充、Flash Attention 2解析(97)
  • 48v转12v芯片48v转5v电源芯片AH7691D
  • Oracle Database 23ai 内置 SQL 防火墙启用
  • MySQL 31 误删数据怎么办?
  • 微前端面试题及详细答案 88道(09-18)-- 核心原理与实现方式
  • VBA技术资料MF362:将窗体控件添加到字典
  • 【Leetcode】高频SQL基础题--1321.餐馆营业额变化增长
  • Redis 中 Intset 的内存结构与存储机制详解
  • uniapp打包前端项目
  • cka解题思路1.32-3
  • 如何解决模型的过拟合问题?
  • 2025牛客周赛108场e题
  • 【课堂笔记】复变函数-2
  • 25、优化算法与正则化技术:深度学习的调优艺术
  • qt QCategoryAxis详解
  • 云游戏时代,游戏盾如何保障新型业务的流畅体验