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.json

Gemini还给出这个方案:

为了确保静态资源总是从站点的根目录加载,您需要在您的 public/index.html 文件中(或者您的 React 应用的入口 HTML 文件)使用绝对路径来引用您的 JavaScript、CSS 和其他静态文件。

<!--错误写法-->
<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">
HTML

发现我经过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.js

P.S. 使用 firebase emulators:start 可以在本地模拟hosting服务,以便调试。

Leave a Reply

Your email address will not be published. Required fields are marked *