You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

部署在Azure Web App的React应用商品页刷新空白问题求助

问题:React应用部署Azure Web App Service后刷新异常

问题现象

  • 初始部署后,登录页可正常渲染,但刷新页面时显示错误:

The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.

  • 添加web.config文件后多数功能恢复正常,但商品页仍存在异常:点击进入商品页可正常渲染,刷新后页面变为空白,且页面logo不显示、头部导航菜单无法点击。控制台显示静态资源(如图片、样式文件)出现404错误,原因是资源路径解析错误。

相关代码

index.js

import React, { useState, useEffect } from 'react';
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
import ReactDOM from 'react-dom/client';
import Header from './header.js';
import Product from './product.js';
import MainPage from './main.js';
import Cart from './cart.js';
import Login from './login.js';
import Admin from './adminDashboard.js';
import { getUserDataFromToken } from './authService';

// 检查用户是否已认证
function isAuthenticated() {
    const token = localStorage.getItem('userToken');
    if (token) {
        const payload = JSON.parse(atob(token.split('.')[1]));
        // 检查token是否过期
        return payload.exp > Date.now() / 1000;
    }
    return false;
}

// 保护路由组件
function PrivateRoute({ children }) {
    return isAuthenticated() ? children : <Navigate to="/login" />;
}

function App() {
    const [user, setUser] = useState(null);

    useEffect(() => {
        const userData = getUserDataFromToken();
        if (userData) {
            setUser(userData.email);
        }
    }, []);
    
    return (
        <BrowserRouter>
            <div>
                <Routes>
                    <Route index element={<PrivateRoute><MainPage/></PrivateRoute>} />
                    <Route path="/product/:productId" element={<PrivateRoute><Product product={6}/></PrivateRoute>} />
                    <Route path="" element={<PrivateRoute><Cart /></PrivateRoute>} />
                    <Route path="/admin" element={<Admin />} />
                    <Route path="/login" element={<Login />} />
                </Routes>
            </div>
        </BrowserRouter>
    );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

product.jsx

import { useState, useEffect } from 'react';
import Header from './header.js';
import ProductImages from './ProductImages.js';
import ProductDetails from './ProductDetails.js';
import Comments from './Comments.js';
import AddReview from './AddReview.js';
import styles from './product.module.css';

function App() {
    let productID = window.location.pathname.split('/')[window.location.pathname.split('/').length-1];
    var [CurrentProduct, setProduct] = useState([]);
    var [loading, setLoading] = useState(true);
    useEffect(() => {
        const url = "https://myapi.net/Product/FindProduct/" + productID;
        fetch(url)
            .then((response) => response.json())
            .then((data) => setProduct(data));
            console.log("GETTING DATA FROM SERVER");
            setLoading(false);
    }, [loading]);

    console.log(CurrentProduct);
    if (loading)
    {
        return <p>Loading...</p>;
    }

    if (!loading && CurrentProduct.id > 0)
    {
        return (
            <div className={styles.productPage}>
                    <Header />
            <div className={styles.fullPage}>
                    <ProductImages product={CurrentProduct} />
                    <ProductDetails product={CurrentProduct} />
                    <Comments product={CurrentProduct} />
                    <AddReview product={CurrentProduct} setLoading={setLoading} />
            </div>
            </div>
        );
    }
}
export default App;

解决建议

  • 修正web.config重写规则:确保静态资源不被重定向,所有路由请求都指向index.html。替换为以下配置:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <!-- 静态资源直接返回,跳过重写 -->
        <rule name="Static Files" stopProcessing="true">
          <match url="([\S]+[.](html|css|js|png|jpg|jpeg|gif|ico|svg))" />
          <action type="None" />
        </rule>
        <!-- 非文件/目录请求重写到index.html -->
        <rule name="React Routes" stopProcessing="true">
          <match url=".*" />
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
          </conditions>
          <action type="Rewrite" url="/index.html" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>
  • 使用绝对路径引用静态资源:将所有静态资源路径改为根目录开头,比如/images/logo.png,避免路由变化导致资源路径解析错误。
  • 用useParams获取路由参数:替换手动解析路径的方式,避免错误:
import { useParams } from 'react-router-dom';

function Product() { // 组件名改为Product,避免与根App冲突
    const { productId } = useParams();
    // 后续使用productId作为参数
}
  • 修复product.jsx的useEffect逻辑:修正依赖和异步处理,避免无限循环和提前结束加载:
useEffect(() => {
    setLoading(true);
    const url = `https://myapi.net/Product/FindProduct/${productId}`;
    fetch(url)
        .then(res => res.json())
        .then(data => setProduct(data))
        .catch(err => console.error('加载商品失败:', err))
        .finally(() => setLoading(false));
}, [productId]); // 依赖改为productId,而非loading
  • 补充组件默认返回逻辑:在product.jsx末尾添加默认返回,避免页面空白:
// 现有逻辑后添加
return <p>商品不存在或加载失败</p>;
  • 修正Cart路由路径:index.js中Cart的路径path=""会和首页路由冲突,改为path="/cart":
<Route path="/cart" element={<PrivateRoute><Cart /></PrivateRoute>} />

内容的提问来源于stack exchange,提问作者Руслан Василев

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 21:58:09