Firebase踩坑
由于我的单页面应用使用了react-router-dom做页面路由:
通过路由foo,传递一个id参数,渲染组件”Component“。
ReactDom.render(
<Router>
<Switch>
<Route path="/foo/:id" component={Component} />
<Route path="*" component={ () => <div>404 Page Not Found</div> } />
</Switch>
</Router>
,
rootElement,
);
TypeScript在访问domain.com/404时,可以正常渲染not found文本。
但在访问domain.com/foo/123时,浏览器从错误的路径请求了静态资源。静态资源会从domain.com/foo/js/xxx.js加载。然而真正的资源存储在domain.com/js/xxx.js。
尝试了常见的解决方案(配置firebase的rewrite规则),但问题依然存在。
{
"hosting": {
// ...
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
firebase.jsonGemini还给出这个方案:
为了确保静态资源总是从站点的根目录加载,您需要在您的
public/index.html
文件中(或者您的 React 应用的入口 HTML 文件)使用绝对路径来引用您的 JavaScript、CSS 和其他静态文件。HTML<!--错误写法--> <script src="./js/xxx.js"></script> <link rel="stylesheet" href="css/style.css"> <!--正确写法--> <script src="/js/xxx.js"></script> <link rel="stylesheet" href="/css/style.css">
发现我经过webpack打包的静态html文件,确实是以相对路径引入资源。
因此在生产环境的webpack设置中修改文件名即可。
module.exports = merge(baseConfig, {
mode: 'production',
entry: {
app: ['core-js/stable', path.resolve(__dirname, 'src/index.tsx')],
},
output: {
path: path.resolve(__dirname, 'public'),
filename: 'js/[name].[contenthash].js',
chunkFilename: 'js/[id].[contenthash].js',
//publicPath: './', 相对路径
publicPath: '/', // 绝对路径
},
webpack.prod.jsP.S. 使用 firebase emulators:start
可以在本地模拟hosting服务,以便调试。