
簡介本資源是一份面向Java全棧開發(fā)者與運維人員的若依RuoYi前后端分離項目實戰(zhàn)部署指南聚焦LinuxNginx與WindowsTomcat雙環(huán)境落地難點系統(tǒng)解決部署后404頁面、跨域調(diào)用第三方API如百度地圖等高頻問題。文檔以實操為導向完整覆蓋后臺jar/war包構(gòu)建、前端dist目錄部署、Redis緩存配置、Nginx反向代理設置、Tomcat Context路徑定制及web.xml容錯配置等關(guān)鍵環(huán)節(jié)并附Vue路由路徑修正、CORS策略配置等排錯細節(jié)。資源為1個223KB的Word文檔.docx結(jié)構(gòu)清晰、圖文結(jié)合含命令示例、配置代碼片段與典型錯誤歸因分析便于快速查閱與現(xiàn)場實施。目前已有7766人學習下載適合剛接觸若依框架、需獨立完成生產(chǎn)環(huán)境部署的中初級開發(fā)者高效上手。1. “菜單打不開”“登錄后空白頁”“404 刷不出來”——若依前后端分離部署里最玄學的三連擊90% 的人卡在這三步就放棄重裝你剛把若依RuoYi前后端分離版打包好scp 傳到服務器、nohup 啟動 jar、nginx reload 完畢瀏覽器輸入http://xxx.xxx.xxx.xxx—— 登錄頁出來了輸入賬號密碼一按回車頁面白了。F5 刷新404。點左側(cè)菜單沒反應控制臺報Failed to load resource: the server responded with a status of 404 (Not Found)。再查 nginx 日志全是*1 open() /usr/share/nginx/html/profile/xxxx failed (2: No such file or directory)。你翻遍文檔、搜遍論壇有人說改vue.config.js有人說加web.xml有人說刪掉publicPath前面的點有人說要配history模式 fallback……越試越亂最后默默刪庫重來。這不是你技術(shù)不行是若依這套部署鏈路里埋了三個「默認不報錯但必然失效」的隱性斷點前端路由模式與服務端靜態(tài)資源路徑不匹配、Nginx 未正確處理 history 跳轉(zhuǎn)、Tomcat 對單頁應用SPA的 404 沒兜底。這篇筆記不講“怎么安裝 Redis”只聚焦這三類高頻翻車現(xiàn)場——它們不是配置錯誤而是若依作為一套真實生產(chǎn)級框架在脫離開發(fā)環(huán)境npm run serve后對部署側(cè)提出的明確契約要求。如果你正被“菜單加載失敗”“空白頁”“跨域 404”反復暴擊這篇就是你的后悔藥。2. 登錄成功但菜單空白/跳轉(zhuǎn) 404Vue Router history 模式 Nginx 靜態(tài)服務的致命錯配若依前端基于 Vue Router默認啟用history模式非hash模式這意味著 URL 是/system/user而非/#/system/user。好處是美觀、SEO 友好壞處是——所有非根路徑的請求都必須由前端接管否則服務端會當成真實文件路徑去查找找不到就 404。而 Nginx 默認行為正是收到/system/user請求就去root /usr/share/nginx/html;目錄下找system/user/index.html這個文件。它當然不存在于是返回 404。此時 Vue Router 根本沒機會啟動更別說渲染菜單了。這不是前端代碼 bug是服務端沒履行“把所有非 API 請求都 fallback 到index.html”的約定。2.1 根因深挖為什么location /塊里不加try_files就必然白屏看若依文檔里那句輕描淡寫的“修改 nginx.conf”很多人只改了proxy_pass代理后端 API卻漏掉了最關(guān)鍵的location /塊配置。標準 Nginx 配置中l(wèi)ocation /控制所有以/開頭的請求。若此處僅寫location / { root /usr/share/nginx/html; index index.html; }Nginx 會嚴格按字面路徑查找文件/system/user→ 查/usr/share/nginx/html/system/user→ 無此目錄 → 404。而 Vue Router 的history模式要求只要請求不是.js/.css/.png等靜態(tài)資源且不是/prod-api/這類 API 前綴就一律返回index.html讓前端 JS 自己解析路由。這個邏輯必須由try_files指令實現(xiàn)。2.2 正確解法Nginx 必須啟用try_filesfallback機制在nginx.conf的server塊內(nèi)找到或新增location /配置徹底替換為以下內(nèi)容注意這是唯一生效方案別再抄網(wǎng)上殘缺片段location / { root /usr/share/nginx/html; try_files $uri $uri/ /index.html; }邏輯說明try_files指令按順序嘗試匹配$uri如/system/user、$uri/如/system/user/若都失敗則強制返回/index.html即前端入口文件。這樣無論用戶直接訪問/、/system/user還是刷新頁面Nginx 都返回index.htmlVue Router 才能初始化并根據(jù) URL 渲染對應組件。參數(shù)說明$uri是原始請求 URI不含 query string$uri/是加斜杠的目錄形式/index.html是 fallback 路徑必須以/開頭表示相對于root的絕對路徑。若root設為/data/www則實際返回/data/www/index.html。2.3 驗證是否生效三步快速自檢檢查 Nginx 配置語法執(zhí)行sudo nginx -t輸出syntax is ok且test is successful才算通過確認靜態(tài)文件位置ls -l /usr/share/nginx/html/必須能看到index.html、favicon.ico、js/、css/等文件即你復制的dist目錄內(nèi)容抓包驗證響應體用瀏覽器開發(fā)者工具 Network 面板訪問/system/user查看 Response Headers 中Content-Type是否為text/htmlResponse Body 是否包含div idapp—— 若是說明 Nginx 成功 fallback 到index.html若仍是 404 或返回空說明location /配置未生效或路徑錯誤。2.4 避坑常見問題與血淚經(jīng)驗現(xiàn)象改完nginx.confnginx -s reload后依然 404原因nginx.conf中存在多個location /塊比如location / { ... }和location /prod-api { ... }并存Nginx 優(yōu)先匹配最長前綴若/prod-api塊寫在/塊前面且未加^~修飾符可能導致/system/user被錯誤匹配到 API 塊。解決確保location /是最外層、最寬泛的塊且放在所有具體路徑如/prod-api、/static之后或給 API 塊加^~強制前綴匹配location ^~ /prod-api { ... }。現(xiàn)象Nginx 返回index.html但控制臺報GET http://ip/js/app.xxx.js net::ERR_ABORTED 404原因前端構(gòu)建時publicPath配置錯誤導致生成的index.html中 JS/CSS 路徑指向/js/app.xxx.js但 Nginx 的root指向/usr/share/nginx/html實際文件在/usr/share/nginx/html/dist/js/下。解決部署前必須修改vue.config.js中的publicPath// vue.config.js module.exports { publicPath: ./, // 關(guān)鍵改為相對路徑而非 / 或 /prod/ }注意./表示相對于index.html當前目錄這樣生成的index.html里script src./js/app.xxx.js才能正確加載。若設為/路徑變成絕對根路徑/js/...Nginx 會在root根目錄下找而非dist子目錄?,F(xiàn)象try_files配置正確但訪問/profile/avatar若依頭像上傳路徑仍 404原因若依后端默認將用戶頭像存于profile/目錄如profile/avatar/xxx.png該路徑屬于靜態(tài)資源需單獨配置location讓 Nginx 直接提供而非 fallback 到index.html。解決在server塊內(nèi)添加獨立locationlocation /profile/ { alias /home/ruoyi/ruoyi-admin/profile/; # 替換為你的實際 profile 目錄絕對路徑 expires 1d; add_header Cache-Control public, immutable; }alias與root區(qū)別alias會完全替換匹配的路徑前綴/profile/avatar.png→ 映射到/home/ruoyi/.../avatar.pngroot是拼接/profile/avatar.png→/home/.../profile/avatar.png。此處必須用alias否則多一層profile。3. Windows Tomcat 部署后空白頁Tomcat 對 SPA 的 404 處理缺失當選擇 Windows Tomcat 方案時若依文檔指導你把dist目錄整個丟進webapps再改server.xml加Context。但很多人忽略了一個殘酷事實Tomcat 本質(zhì)是 Servlet 容器不是靜態(tài)文件服務器它對index.html以外的路徑如/system/user默認不識別直接返回 404且不會像 Nginx 那樣提供try_files機制。你看到的空白頁正是 Tomcat 在webapps/dist/下找不到/system/user這個“Servlet”或“JSP”時拋出的標準 404 頁面或空白。而若依前端需要的是所有 404 都重定向到index.html交由 Vue Router 處理。3.1 根因深挖為什么web.xml是 Tomcat 下 SPA 的唯一救命稻草Tomcat 的web.xml是 Web 應用的部署描述符其中error-page元素允許你定義特定 HTTP 狀態(tài)碼的自定義響應。若依文檔讓你新建WEB-INF/web.xml并配置error-page其核心邏輯是當 Tomcat 內(nèi)部找不到請求路徑時不返回默認 404 頁面而是轉(zhuǎn)發(fā)forward到/index.html。這相當于在 Tomcat 層面實現(xiàn)了 Nginx 的try_files功能。沒有它任何非根路徑的直接訪問或刷新都會觸發(fā) Tomcat 的 404 流程前端 JS 根本沒機會運行。3.2 正確解法web.xml必須精準配置 error-page forward在dist目錄下創(chuàng)建WEB-INF文件夾注意大小寫并在其中新建web.xml內(nèi)容必須嚴格如下XML 聲明和命名空間不可省略?xml version1.0 encodingUTF-8? web-app xmlnshttp://xmlns.jcp.org/xml/ns/javaee xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd version4.0 metadata-completetrue display-nameVue SPA Fallback/display-name error-page error-code404/error-code location/index.html/location /error-page /web-app邏輯說明error-page告訴 Tomcat當發(fā)生 HTTP 404 錯誤時不要返回默認錯誤頁而是內(nèi)部 forward 到/index.html注意是/開頭的路徑表示相對于當前 Web 應用根目錄。Tomcat 會讀取dist/index.html并返回Vue Router 得以啟動。參數(shù)說明version4.0對應 Servlet 4.0 規(guī)范Tomcat 9若用 Tomcat 8請改為3.1并調(diào)整xsi:schemaLocation中的 URLmetadata-completetrue告訴容器無需掃描注解提升啟動速度。3.3 驗證是否生效兩步定位 Tomcat 是否接管 404檢查web.xml位置與權(quán)限確保文件位于dist/WEB-INF/web.xml不是dist/WEB-INF/外層且 Tomcat 啟動用戶對該文件有讀取權(quán)限Windows 下通常無問題觀察 Tomcat 日志啟動 Tomcat 后訪問一個不存在的路徑如/fake/path查看logs/catalina.out或logs/localhost.date.log若看到類似Forwarding to error page from request [...]的日志說明web.xml生效若只有Processing ErrorPage[errorCode404, location/index.html]但無后續(xù)可能是location路徑錯誤。3.4 避坑常見問題與血淚經(jīng)驗現(xiàn)象web.xml已添加但訪問/system/user仍返回 Tomcat 默認 404 頁面帶 Apache Tomcat 字樣原因location值寫成了index.html缺少/前綴導致 Tomcat 嘗試在WEB-INF目錄下找index.html自然失敗。解決location必須以/開頭如/index.html表示應用根目錄下的文件?,F(xiàn)象web.xml生效但index.html加載后控制臺報Uncaught SyntaxError: Unexpected token 原因index.html中引用的 JS/CSS 路徑錯誤。Tomcat 將dist目錄作為 Web 應用根所以publicPath必須設為./相對路徑而非/絕對根路徑。若設為/index.html會請求http://ip:8080/js/app.xxx.js但 Tomcat 實際將dist/js/映射到http://ip:8080/js/路徑不匹配。解決再次確認vue.config.js中publicPath: ./重新npm run build:prod覆蓋dist目錄?,F(xiàn)象web.xml配置正確但登錄后點擊菜單仍跳轉(zhuǎn)失敗Network 面板顯示GET http://ip:8080/system/user 404原因Tomcat 的Context配置未生效或dist目錄未正確部署到webapps。若dist目錄名為myapp則 Tomcat 會將其部署為http://ip:8080/myapp/此時所有請求路徑應為/myapp/system/user但前端router默認 base 是/導致請求發(fā)往根路徑。解決在vue.config.js中顯式設置baseUrlVue CLI 2或publicPathVue CLI 3為應用上下文路徑// vue.config.js (Vue CLI 3) module.exports { publicPath: /myapp/, // 與 Tomcat 部署的 Context Path 一致 }注意publicPath改為/myapp/后index.html中所有資源路徑會自動加上/myapp/前綴如script src/myapp/js/app.xxx.js確保 Tomcat 能正確路由。4. 跨域問題百度地圖等第三方 API 調(diào)用失敗的三種真實場景與解法若依項目常需集成百度地圖、高德地圖、微信 JS-SDK 等第三方服務這些 API 通常要求調(diào)用方域名在白名單內(nèi)。而開發(fā)時npm run serve啟動的http://localhost:80與生產(chǎn)環(huán)境http://your-server-ip域名不同瀏覽器會攔截跨域請求控制臺報CORS header Access-Control-Allow-Origin missing或No Access-Control-Allow-Origin header is present。這不是若依的鍋是瀏覽器同源策略的剛性約束。但解決方案不能只靠“讓后端加 CORS”因為第三方 API 的響應頭由對方服務器控制你無法修改。4.1 根因深挖為什么“后端加 CrossOrigin”對第三方 API 無效CrossOrigin注解Spring Boot或CorsConfiguration是后端服務自己響應時添加Access-Control-Allow-Origin頭用于解決前端 → 若依后端的跨域。但當你在前端 JS 中直接fetch(https://api.map.baidu.com/...)請求是前端 → 百度服務器百度服務器的響應頭里沒有Access-Control-Allow-Origin: *或你的域名瀏覽器就會拒絕。此時若依后端加再多CrossOrigin也無濟于事因為請求根本沒經(jīng)過若依后端。4.2 正確解法必須走“后端代理”繞過瀏覽器同源限制唯一可靠方案是前端請求若依后端的一個代理接口如/proxy/baidu若依后端收到請求后用自己的服務器身份去調(diào)用百度 API再把結(jié)果原樣返回給前端。這樣前端只與同源的若依后端通信無跨域若依后端與百度通信服務器間無同源限制。這需要兩步改造第一步前端配置代理開發(fā)期與統(tǒng)一接口生產(chǎn)期開發(fā)期npm run serve利用 Vue CLI 的devServer.proxy將/proxy/baidu請求代理到若依后端// vue.config.js devServer: { proxy: { /proxy/baidu: { target: http://localhost:8080, // 若依后端地址 changeOrigin: true, pathRewrite: { ^/proxy/baidu: /baidu // 將 /proxy/baidu/xxx 重寫為 /baidu/xxx } } } }生產(chǎn)期部署后前端代碼中所有調(diào)用百度 API 的地方必須改為請求若依后端的代理接口例如// 原始錯誤寫法跨域 // fetch(https://api.map.baidu.com/geocoding/v3/?address北京outputjsonakxxx) // 正確寫法走若依代理 fetch(/prod-api/baidu/geocoding/v3/?address北京outputjsonakxxx)第二步后端實現(xiàn)代理 Controller若依 Spring Boot在若依后端項目中新建一個 Controller負責轉(zhuǎn)發(fā)請求// com.ruoyi.common.controller.ProxyController.java RestController RequestMapping(/baidu) public class ProxyController { private static final String BAIDU_API_BASE https://api.map.baidu.com; GetMapping(/{path:.}) public ResponseEntity? proxyBaidu( PathVariable String path, RequestParam MapString, String params, HttpServletRequest request) throws IOException { // 構(gòu)建完整百度 API URL String url BAIDU_API_BASE / path ? buildQueryString(params); // 使用 RestTemplate 發(fā)起 GET 請求生產(chǎn)環(huán)境建議用 WebClient 或 OkHttp RestTemplate restTemplate new RestTemplate(); HttpHeaders headers new HttpHeaders(); headers.set(User-Agent, Mozilla/5.0); HttpEntityString entity new HttpEntity(headers); try { ResponseEntityString response restTemplate.exchange( url, HttpMethod.GET, entity, String.class); return ResponseEntity.status(response.getStatusCode()) .headers(response.getHeaders()) .body(response.getBody()); } catch (Exception e) { return ResponseEntity.status(500).body(Proxy failed: e.getMessage()); } } private String buildQueryString(MapString, String params) { return params.entrySet().stream() .map(e - e.getKey() URLEncoder.encode(e.getValue(), StandardCharsets.UTF_8)) .collect(Collectors.joining()); } }邏輯說明該 Controller 攔截所有/baidu/**請求提取路徑和查詢參數(shù)拼成百度 API 完整 URL再用RestTemplate以服務器身份發(fā)起請求并將百度的響應狀態(tài)碼、Header、Body 原樣透傳給前端。參數(shù)說明PathVariable String path匹配任意子路徑如geocoding/v3RequestParam MapString, String自動收集所有 query 參數(shù)buildQueryString確保參數(shù)值 URL 編碼避免特殊字符如中文導致百度 API 解析失敗。4.3 避坑常見問題與血淚經(jīng)驗現(xiàn)象代理接口返回 400 或 500百度 API 響應{status:3,message:Invalid request}原因百度 API 的ak密鑰參數(shù)未正確傳遞或ak值在若依后端被 URL 編碼兩次前端已編碼后端又編碼一次。解決在buildQueryString中只對e.getValue()編碼且確保前端傳參時ak是原始字符串不手動編碼或改用UriComponentsBuilder更安全UriComponentsBuilder builder UriComponentsBuilder.fromHttpUrl(url); params.forEach(builder::queryParam); String fullUrl builder.toUriString(); // 自動處理編碼現(xiàn)象代理請求成功但返回的 JSON 中content-type是text/plain前端fetch().json()報錯原因百度 API 響應頭Content-Type可能是text/plain;charsetutf-8而RestTemplate默認不識別返回String類型。解決在RestTemplate請求中顯式指定StringHttpMessageConverter支持text/plainRestTemplate restTemplate new RestTemplate(); ListHttpMessageConverter? converters new ArrayList(); converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8)); converters.add(new MappingJackson2HttpMessageConverter()); restTemplate.setMessageConverters(converters);現(xiàn)象本地開發(fā)代理正常但部署到 Linux 后/prod-api/baidu/...返回 404原因Nginx 配置中/prod-api代理規(guī)則未覆蓋/prod-api/baidu路徑或location /prod-api塊內(nèi)缺少proxy_pass指向后端。解決檢查nginx.conf中l(wèi)ocation /prod-api塊確保proxy_pass指向正確的后端地址如http://127.0.0.1:8080且無^~修飾符導致路徑截斷。5. 啟動失敗/后臺進程消失nohup java -jar的隱形陷阱與健壯守護方案若依文檔推薦用nohup java -jar ruoyi-admin.jar msg.log 21 啟動后端看似簡單實則暗藏三大隱患日志文件無限增長撐爆磁盤、Java 進程意外退出后無人拉起、nohup無法管理進程生命周期無法優(yōu)雅停止。某次服務器重啟后你發(fā)現(xiàn)ps aux | grep ruoyi沒有進程msg.log里最后一行是OutOfMemoryError但沒人知道它何時掛的。這不是運維疏忽是nohup作為 shell 工具根本不具備服務化管理能力。5.1 根因深挖為什么nohup不是生產(chǎn)環(huán)境的正確答案nohup的設計初衷是讓命令在終端關(guān)閉后繼續(xù)運行它只是簡單地將stdout和stderr重定向到nohup.out或你指定的文件然后fork一個子進程執(zhí)行命令。它不監(jiān)控進程健康狀態(tài)、不處理內(nèi)存溢出、不記錄啟動/停止時間、不提供服務啟停腳本。在生產(chǎn)環(huán)境中若依后端可能因 GC 壓力、數(shù)據(jù)庫連接池耗盡、Redis 連接超時等原因崩潰nohup不會感知更不會重啟。你只能靠定時巡檢日志效率極低。5.2 正確解法用systemd替代nohup實現(xiàn)真正的服務化Linux 系統(tǒng)推薦使用systemd現(xiàn)代發(fā)行版標配來管理 Java 服務。它提供進程守護、自動重啟、日志聚合、依賴管理等企業(yè)級能力。步驟如下第一步創(chuàng)建 systemd 服務文件sudo vim /etc/systemd/system/ruoyi-admin.service填入以下內(nèi)容請根據(jù)你的實際路徑修改[Unit] DescriptionRuoyi Admin Service Afternetwork.target redis.service Wantsredis.service [Service] Typesimple Userruoyi WorkingDirectory/home/ruoyi/ruoyi-admin ExecStart/usr/bin/java -Xms512m -Xmx1024m -Dfile.encodingUTF-8 -jar /home/ruoyi/ruoyi-admin/ruoyi-admin.jar Restartalways RestartSec10 SuccessExitStatus143 StandardOutputjournal StandardErrorjournal SyslogIdentifierruoyi-admin [Install] WantedBymulti-user.target邏輯說明[Unit]定義服務依賴啟動前確保網(wǎng)絡和 Redis 就緒[Service]是核心Typesimple表示主進程即 Java 進程Userruoyi指定非 root 用戶運行安全最佳實踐ExecStart是啟動命令-Xms/-Xmx設置 JVM 內(nèi)存Restartalways確保進程崩潰后自動重啟StandardOutputjournal將日志接入systemd日志系統(tǒng)無需手動管理msg.log。參數(shù)說明RestartSec10表示重啟間隔 10 秒SuccessExitStatus143將SIGTERM優(yōu)雅停止的退出碼視為成功避免systemctl stop后被誤判為失敗重啟。第二步啟用并啟動服務# 重載 systemd 配置 sudo systemctl daemon-reload # 啟用開機自啟 sudo systemctl enable ruoyi-admin.service # 啟動服務 sudo systemctl start ruoyi-admin.service # 查看狀態(tài)關(guān)鍵 sudo systemctl status ruoyi-admin.service # 查看實時日志替代 cat msg.log sudo journalctl -u ruoyi-admin.service -f5.3 驗證是否生效三招確認 systemd 守護到位檢查進程歸屬ps aux | grep ruoyi-adminUSER列應為ruoyi非rootCMD列應為完整java -Xms...命令模擬崩潰測試sudo kill -9 $(pgrep -f ruoyi-admin.jar)等待 10 秒執(zhí)行sudo systemctl status ruoyi-admin.service應顯示active (running)且Main PID變化日志檢索能力sudo journalctl -u ruoyi-admin.service --since 2 hours ago | grep Started能精準查到啟動記錄證明日志已接入systemd。5.4 避坑常見問題與血淚經(jīng)驗現(xiàn)象systemctl start后狀態(tài)為failedjournalctl顯示Permission denied原因ruoyi用戶對ruoyi-admin.jar或application.yml文件無讀取權(quán)限或WorkingDirectory目錄不可訪問。解決sudo chown -R ruoyi:ruoyi /home/ruoyi/ruoyi-adminsudo chmod 755 /home/ruoyi/ruoyi-admin確保所有文件屬主為ruoyi?,F(xiàn)象服務啟動成功但http://ip:8080無法訪問netstat -tuln | grep 8080無監(jiān)聽原因若依后端application.yml中server.port被注釋或設為0隨機端口或spring.profiles.active指向的配置文件未正確加載。解決檢查ruoyi-admin.jar內(nèi)BOOT-INF/classes/application.yml確認server.port: 8080未被注釋若使用外部配置確保--spring.config.locationfile:/home/ruoyi/ruoyi-admin/config/參數(shù)已加入ExecStart?,F(xiàn)象systemctl stop后進程仍在ps aux還能看到 Java 進程原因Java 進程未響應SIGTERM可能因線程阻塞或未注冊 Shutdown Hook。解決在若依后端Application.java中添加優(yōu)雅關(guān)閉邏輯SpringBootApplication public class RuoyiAdminApplication { public static void main(String[] args) { ConfigurableApplicationContext context SpringApplication.run(RuoyiAdminApplication.class, args); // 注冊 JVM 關(guān)閉鉤子 Runtime.getRuntime().addShutdownHook(new Thread(() - { System.out.println(Shutting down Ruoyi Admin gracefully...); // 此處可關(guān)閉線程池、釋放資源 })); } }6. 如何 5 分鐘內(nèi)定位部署故障一份可立即執(zhí)行的排查清單與決策樹從第一次部署若依到現(xiàn)在我給自己立下鐵律任何部署問題必須在 5 分鐘內(nèi)鎖定根因否則立刻執(zhí)行標準化排查流程。這套流程不是憑空而來是踩過“Nginx 配置漏掉try_files”、“Tomcatweb.xml位置放錯”、“publicPath用/而非./”等上百個坑后提煉出的最小可行路徑。它不依賴經(jīng)驗直覺只依賴可驗證的事實?,F(xiàn)在我把這份清單交給你照著做5 分鐘出答案。6.1 第一步確定故障類型30 秒打開瀏覽器開發(fā)者工具F12切到 Network 面板刷新頁面觀察第一個請求通常是index.html的狀態(tài)碼如果是 200前端資源加載成功問題在 JS 執(zhí)行或后端 API跳到第 3 步如果是 404Nginx/Tomcat 未正確提供index.html問題在服務端靜態(tài)資源配置跳到第 2 步如果是 502/503Nginx 無法連接后端如proxy_pass地址錯誤、后端未啟動問題在反向代理跳到第 4 步。提示不要看控制臺 Console 的 JS 錯誤那是結(jié)果不是原因。先看 Network 的 HTTP 狀態(tài)碼它是真相的源頭。6.2 第二步驗證靜態(tài)資源服務90 秒針對 404 故障執(zhí)行以下命令Linux# 1. 檢查 Nginx 配置中 root 路徑是否指向 dist 目錄 sudo nginx -T 2/dev/null | grep -A 5 location / # 2. 確認 dist 目錄存在且有 index.html ls -l /usr/share/nginx/html/index.html # Nginx 路徑 # 或 ls -l /home/ruoyi/tomcat/webapps/dist/index.html # Tomcat 路徑 # 3. 檢查 Nginx 是否監(jiān)聽 80 端口 sudo ss -tuln | grep :80 # 4. 如果是 Tomcat確認 web.xml 是否在正確位置 ls -l /home/ruoyi/tomcat/webapps/dist/WEB-INF/web.xml若root路徑錯誤 → 修改nginx.conf若index.html不存在 → 重新npm run build:prod并復制dist若ss無輸出 →sudo systemctl start nginx若web.xml不存在 → 按第 3 章方法重建。6.3 第三步驗證前端路由與資源路徑120 秒若index.html返回 200但頁面白屏或菜單不加載# 1. 查看 index.html 源碼確認 script 標簽 src 路徑 curl -s http://localhost/index.html | grep src\ # 2. 檢查該 JS 文件是否能直接訪問替換為實際路徑 curl -I http://localhost/js/app.xxx.js # 應返回 200 # 3. 檢查 Vue Router base 是否匹配 curl -s http://localhost/index.html | grep BASE_URL\|publicPath若src是/js/...但返回 404 →vue.config.js中publicPath必須為./若src是./js/...但返回 404 → Nginxroot路徑未指向dist目錄或 Tomcatdist未本文還有配套的精品資源點擊獲取