React应用部署Firebase后空白页及Router组件报错求助
问题汇总与求助
一、线上部署的manifest.json解析错误
错误信息
Uncaught SyntaxError: Unexpected token '<' manifest.json:1 Manifest: Line: 1, column: 1, Syntax error.
问题现象
站点请求manifest.json时返回的是index.html内容,但本地build目录下的manifest.json内容完全正常。
项目目录结构
└--.firebase └--.github └--workflows └--firebase-hosting-merge.yml └--firebase-hosting-pull-request.yml └--build └--node_modules └--public └--404.html └--favicon.ico └--index.html └--logo192.png └--logo512.png └--manifest.json └--robots.txt └--src └--components └--App.js └--AuthForm.js └--Navigation.js └--Nweet.js └--NweetFactory.js └--routes └--Auth.js └--Home.js └--Profile.js └--Router.js └--fbase.js └--index.js └--styles.css └--.env └--.firebaserc └--.gitignore └--firebase.json └--jsconfig.json └--package.json └--package-lock.json └--README.md
manifest.json内容
{ "short_name": "React App", "name": "Create React App Sample", "icons": [ { "src": "favicon.ico", "sizes": "64x64 32x32 24x24 16x16", "type": "image/x-icon" }, { "src": "logo192.png", "type": "image/png", "sizes": "192x192" }, { "src": "logo512.png", "type": "image/png", "sizes": "512x512" } ], "start_url": ".", "display": "standalone", "theme_color": "#000000", "background_color": "#ffffff" }
已尝试的解决方案
- 检查
index.html中manifest引用路径,使用%PUBLIC_URL%/manifest.json确保路径正确 - 修改
firebase.json的public字段为"build" - 在GitHub Actions中配置
PUBLIC_URL环境变量
二、本地运行的路由组件错误
错误信息
[Routes] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>
当前Router.js代码
import { HashRouter as Router, Routes, Route } from "react-router-dom"; import Auth from "./Auth"; import Home from "./Home"; import Profile from "./Profile"; import Navigation from "../components/Navigation"; const AppRouter = ({isLoggedIn, userObj, refreshUser}) => { return ( <Router> {isLoggedIn && <Navigation userObj={userObj} />} <Routes> <Routes path="/" element={ isLoggedIn ? ( <div style={{ maxWidth: 890, width: "100%", margin: "0 auto", marginTop: 80, display: "flex", justifyContent: "center", }}> <Route exact path="/" element={<Home userObj={userObj}/>} /> <Route exact path="/profile" element={<Profile refreshUser={refreshUser} userObj={userObj} />} /> </div> ) : ( <Route path="/" element={<Auth />} /> )}> </Routes> </Routes> {/*<Navigate from="*" to="/">*/} </Router> ); }; export default AppRouter;
解决方案
针对manifest.json错误
问题根源是Firebase Hosting的rewrites规则将所有请求都导向index.html,包括静态资源请求。需要在firebase.json中添加例外规则,让静态资源直接返回文件:
修改后的firebase.json:
{ "hosting": { "public": "build", "ignore": [ "firebase.json", "**/.*", "**/node_modules/**" ], "rewrites": [ { "source": "**/*.@(json|png|ico|txt)", "destination": "$1" }, { "source": "**", "destination": "/index.html" } ] } }
该规则会优先匹配所有json、png、ico、txt格式的静态资源,直接返回对应文件,其余请求再导向index.html。
针对路由组件错误
react-router-dom v6要求<Routes>的直接子元素只能是<Route>或<React.Fragment>,不能嵌套<Routes>,也不能在element属性中放置其他<Route>。修改后的Router.js:
import { HashRouter as Router, Routes, Route } from "react-router-dom"; import Auth from "./Auth"; import Home from "./Home"; import Profile from "./Profile"; import Navigation from "../components/Navigation"; const AppRouter = ({isLoggedIn, userObj, refreshUser}) => { return ( <Router> {isLoggedIn && <Navigation userObj={userObj} />} <div style={{ maxWidth: 890, width: "100%", margin: "0 auto", marginTop: isLoggedIn ? 80 : 0, display: "flex", justifyContent: "center", }}> <Routes> {isLoggedIn ? ( <> <Route path="/" element={<Home userObj={userObj}/>} /> <Route path="/profile" element={<Profile refreshUser={refreshUser} userObj={userObj} />} /> </> ) : ( <Route path="/" element={<Auth />} /> )} </Routes> </div> </Router> ); }; export default AppRouter;
说明:
- 将布局用的
div移到<Routes>外部,避免路由嵌套错误 - 用
<>(React.Fragment简写)包裹登录状态下的多个<Route>,符合v6语法要求 - 根据
isLoggedIn状态切换渲染对应的路由组
内容的提问来源于stack exchange,提问作者BarrelZebra 2149
相关产品推荐
相关产品推荐

