者:boot-react SinglePageAppConfig pushState 資源解析器深度剖析)
SPA 刷新 404 難題終結(jié)者boot-react SinglePageAppConfig pushState 資源解析器深度剖析【免費(fèi)下載鏈接】boot-reactA starter application with spring boot and react項(xiàng)目地址: https://gitcode.com/gh_mirrors/bo/boot-reactboot-react是一個(gè)基于 Spring Boot React 的單頁應(yīng)用SPA啟動(dòng)器項(xiàng)目其核心類SinglePageAppConfig實(shí)現(xiàn)了一個(gè)pushState 資源解析器從根源上解決了 SPA 應(yīng)用中刷新頁面 404這一經(jīng)典難題讓 React Router 的 History 模式在后端服務(wù)器上也能完美工作。 為什么 SPA 刷新頁面會(huì) 404先搞懂問題本質(zhì)才能理解解決方案的巧妙之處。場景用戶操作瀏覽器實(shí)際請求結(jié)果正常點(diǎn)擊導(dǎo)航點(diǎn)私有頁鏈接無請求JS 內(nèi)部跳轉(zhuǎn)? 頁面正常刷新頁面在/private按 F5GET /private? 服務(wù)器返回 404React Router 默認(rèn)使用瀏覽器的History APIpushState來生成/login、/private這類干凈的 URL。URL 變化時(shí)并沒有真正向后端發(fā)起請求所以平時(shí)一切正常。但一旦刷新頁面瀏覽器會(huì)帶著完整 URL 向服務(wù)器發(fā)真實(shí)請求。而服務(wù)器上根本不存在名為private的文件或接口——它只是前端路由于是服務(wù)器一臉懵地返回 404。 核心矛盾前端路由是虛擬的而 HTTP 請求是真實(shí)的。boot-react 的前端路由定義在frontend/src/router/router.js中包含/首頁列表、/private需登錄的私有頁見frontend/src/router/privateRoute.js、/login、/logout等路由。? boot-react 的雙環(huán)境解決方案boot-react 針對開發(fā)和生產(chǎn)兩個(gè)環(huán)境分別做了處理思路殊途同歸把所有找不到真實(shí)文件的請求統(tǒng)統(tǒng)回退fallback到index.html再交給 React Router 接管。開發(fā)環(huán)境connect-history-api-fallback開發(fā)時(shí)前端由獨(dú)立的 Express 開發(fā)服務(wù)器托管項(xiàng)目用一行代碼引入中間件 connect-history-api-fallback 實(shí)現(xiàn)回退frontend/server.js同時(shí)/api開頭的請求被代理到后端的localhost:8080實(shí)現(xiàn)前后端聯(lián)調(diào)零配置。生產(chǎn)環(huán)境SinglePageAppConfig 登場生產(chǎn)環(huán)境中前端構(gòu)建產(chǎn)物index.html 打包后的 JS/CSS會(huì)被打進(jìn) Spring Boot 的 jar 包由 Spring MVC 的靜態(tài)資源處理器統(tǒng)一分發(fā)。boot-react 通過SinglePageAppConfig類注冊了一個(gè)自定義資源解析器源碼位于backend/src/main/java/react/config/SinglePageAppConfig.java 深度剖析pushState 資源解析器的工作流程SinglePageAppConfig繼承WebMvcConfigurerAdapter攔截所有路徑/**并把靜態(tài)資源指向classpath:/static/最后掛上一個(gè)內(nèi)部類PushStateResourceResolver。它的決策邏輯非常清晰只需三步是 API 請求嗎路徑在忽略列表api中 → 不處理交還給 REST 接口是靜態(tài)資源嗎路徑擴(kuò)展名命中白名單js、css、html、png、svg、woff等 14 種→ 去static目錄找真實(shí)文件都不是→ 判定為前端路由直接返回index.html核心解析方法resolve()的邏輯示意如下private Resource resolve(String requestPath, List? extends Resource locations) { if (isIgnored(requestPath)) { // /api/** 交給后端 return null; } if (isHandled(requestPath)) { // 帶資源擴(kuò)展名 → 找真實(shí)文件 return locations.stream() .map(loc - createRelative(loc, requestPath)) .filter(resource - resource ! null resource.exists()) .findFirst() .orElseGet(null); } return index; // 其他一切 → index.html }就這么簡單得益于這個(gè)解析器用戶在/private刷新時(shí)服務(wù)器返回index.html200 OKReact 加載后讀取瀏覽器地址欄 URLReact Router 匹配到private路由并渲染私有頁完美閉環(huán) ? 快速上手一鍵運(yùn)行 boot-react想親手體驗(yàn)三步搞定1?? 克隆倉庫git clone https://gitcode.com/gh_mirrors/bo/boot-react cd boot-react2?? 安裝前端依賴需要 Node 6.0 和 yarncd frontend yarn3?? 啟動(dòng)應(yīng)用./gradlew bootRun啟動(dòng)后端時(shí)前端熱重載開發(fā)服務(wù)器會(huì)自動(dòng)拉起訪問http://localhost:3000即可看到示例應(yīng)用。生產(chǎn)模式打包部署則執(zhí)行./gradlew clean assemble java -jar backend/build/libs/boot-react-0.0.1-SNAPSHOT.jar此時(shí)刷新/private不再 404正是SinglePageAppConfig在背后默默工作。 關(guān)鍵文件速查表文件作用backend/src/main/java/react/config/SinglePageAppConfig.java? 生產(chǎn)環(huán)境 pushState 資源解析器本文主角frontend/server.js開發(fā)服務(wù)器含 history 回退與 API 代理frontend/src/router/router.jsReact Router 路由表定義frontend/src/router/privateRoute.js受保護(hù)路由未登錄自動(dòng)跳轉(zhuǎn)登錄頁frontend/assets/index-template.htmlSPA 掛載入口div idrootfrontend/webpack.dev.config.js開發(fā)環(huán)境構(gòu)建與熱重載配置backend/src/main/java/react/config/SecurityConfiguration.javaSpring Security 安全配置README.adoc項(xiàng)目完整使用文檔 總結(jié)boot-react 用不到百行的SinglePageAppConfig給出了 SPA 刷新 404 問題的教科書式解法?白名單區(qū)分靜態(tài)資源與路由請求互不干擾?兜底返回 index.html讓前端路由完全接管? 開發(fā)/生產(chǎn)雙環(huán)境方案開箱即用無論是學(xué)習(xí) Spring Boot 集成 React還是尋找一個(gè)干凈、完整、帶熱重載和測試的 SPA 起步模板boot-react 都值得納入你的工具箱。【免費(fèi)下載鏈接】boot-reactA starter application with spring boot and react項(xiàng)目地址: https://gitcode.com/gh_mirrors/bo/boot-react創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考