Asp.net 带有 React 模板的核心 Web 应用程序:在开发中,服务器首先检查 mvc 路由,但在生产中仅检查服务器 returns index.html

Asp.net core web application with react template: in development, server checks mvc routes first, but in prodcution the server only returns index.html

我正在尝试将使用 razor 页面的现有 MVC 应用程序迁移到 Web API + ReactJS 客户端。我正在逐步执行此操作,这意味着我已经迁移了主页 (Home/Index) 以及其他一些 pages/features 以做出反应。 razor 页面和在 react 中实现的页面之间存在链接。这在 运行s 反应开发服务器的开发环境中完美运行。

例如在开发环境中,如果我路由到 localhost:12345/Controller/Action(对于可用的控制器和操作)服务器执行相应的操作和 returns 正确的视图,如果我尝试访问一条服务器未知的路由 returns index.html 并且 react-router 从这一点开始处理路由。这是公认的行为,在开发环境中非常有效。

但是当我在生产模式下构建 React 应用程序和 运行 应用程序时,情况发生了变化。请求永远不会到达服务器,并由 react-router 在客户端处理。当我硬刷新页面时,它会触发已接受的 MVC 操作。

我希望在产品开发中具有相同的行为。

这是 starup.cs 文件的样子。

        // ConfigureServices
        .
        .
        .
        // In production, the React files will be served from this directory
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ReactSource/build";
        });
        .
        .
        .


       
        // Configure
        .
        .
        .
        app.UseStaticFiles();
        app.UseSpaStaticFiles();
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller}/{action}");
        });


        app.UseSpa(spa =>
        {
            spa.Options.SourcePath = "ReactSource";

            // do not start the react development server in production
            if (env.IsDevelopment()) { spa.UseReactDevelopmentServer(npmScript: "start"); }
        });
        .
        .

知道我在这里遗漏了什么吗?我应该为此修改 react-router 吗?

我通过关闭(注销)开箱即用的服务工作者解决了我的问题,它试图缓存资产并阻止请求到达服务器。

在 index.js 文件中,我只是导入了 { unregister } from "./registerServiceWorker" 并在自动生成的 index.js 文件末尾用 unregister(); 替换了 registerServiceWorker();

要拥有一个 Progress Web 应用程序,您必须在您的 React 网络应用程序中启用 Service worker。

要解决生产模式下的缓存问题,您必须在index.tsx文件中输入以下代码:

ReactDOM.render(
    <BrowserRouter basename={baseUrl}>
        <App />
    </BrowserRouter>,
    rootElement);

//index page is Route exact path.
if (window.location.href.includes('index'))
    registerServiceWorker();
else
    unregisterAndReload();

function unregisterAndReload() {
    navigator.serviceWorker.ready.then(registration => {
        registration.unregister().then(() => {
            window.location.reload();
        });
    });
}

和 App.tsx 文件应如下所示:

render() {
        return (
            <Layout>
                <Route exact path='/index' component={Home} />
                <Route path='/contact' component={ContactUs} />
            </Layout>
        );
    }