My SPA files are giving 404 errors when serving the SPA in a branch of the request pipeline. How do I make my static files available to my SPA?

余生长醉 提交于 2020-01-23 19:47:29

问题


First of, in my project root I have a folder called ClientApp, which contains a folder build which is where the output of my frontend build is located.

Then, in Startup.cs, I have the following in ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    ...

    services.AddSpaStaticFiles(configuration => {
        configuration.RootPath = "ClientApp/build";
    });
}

Following, my Configure method looks as follows:

 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
 {
     if (env.IsDevelopment()) {
         app.UseDeveloperExceptionPage();
     } else {
         app.UseExceptionHandler("/Error");
         app.UseHsts();
     }

     app.UseHttpsRedirection();
     app.UseStaticFiles();
     app.UseSpaStaticFiles();
     app.UseAuthentication();

     app.UseMvcWithDefaultRoute();

     app.Map("/dashboard", dashboard => {
         dashboard.Use(async (context, next) => {
             if (context.User.Identity.IsAuthenticated) {
                 await next();
                 return;
             }

             context.Response.Redirect("/Account/Login");
         });

         dashboard.UseSpa(spa => {
             spa.Options.SourcePath = "ClientApp";

             if (env.IsDevelopment()) {
                 spa.UseProxyToSpaDevelopmentServer("http://localhost:3000");
            }
        });
    });
}

If I remove the .Map(...) and just serve the spa in on the app IApplicationBuilder instance, then it works.

Thank you in advance for any help, this has been bugging me for a few days now.

Edit The setup I would want in the end is as follows. /dashboard would serve a SPA application, and anyone accessing that route has to be authenticated. However, routes such as /Account/Login would not be part of the SPA.

By moving UseSpa outside of the Map, any routes that are not handled by the Mvc or a static file in wwwroot will render the SPA, but when visiting e.g. /about I want to show a 404, not the SPA which renders the 404.


回答1:


Right, after some clarification and help from Edward, I was able to identify the problem. As Edward pointed out, since the call to UseSpa was done inside a branch of the request pipeline, the static assets which are served at ClientApp/build are not used since the request for those assets starts with /static/ and not /dashboard. This means the request pipeline is unaware of them.

The fix I found is actually more on the client build than the server, since I was unable to correctly let the server know about the static assets. The fix requires to set the homepage property in package.json as documented here. The only downside to this is that this does not work whilst running npm start since the build is not actually output to the filesystem but is instead in memory of the web-server.

On the server, I did have to move app.UseSpaStaticFiles() inside of the Map call in order for it to work correctly.

Thanks again to Edward for helping me better understand how Map works.




回答2:


For app.Map, it will route the request based on path https://localhost:44378/dashboard/. Which means only requests with https://localhost:44378/dashboard/ will go into the Spa middleware.

For dashboard.UseSpa, it will survery spa static files with https://localhost:44378/styles.bundle.css which will not match https://localhost:44378/dashboard/.

If you did not want to change the request base path in SPA to https://localhost:44378/dashboard/, you may try move UseSpa outside of app.Map("/dashboard".

        app.UseSpa(spa =>
        {
            // To learn more about options for serving an Angular SPA from ASP.NET Core,
            // see https://go.microsoft.com/fwlink/?linkid=864501

            spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                spa.UseAngularCliServer(npmScript: "start");
            }
        });
        app.Map("/dashboard", dashboard =>
        {
            dashboard.Use(async (context, next) =>
            {
                if (context.User.Identity.IsAuthenticated)
                {
                    await next();
                    return;
                }
                context.Response.Redirect("/Account/Login");
            });
        });

Update

For changing SPA Static files request URL, you could try to change package.json like below:

"start": "ng serve --base-href=/dashboard/ --serve-path=/ --live-reload-client=https://localhost:port/frontend/sockjs-node/",

For another option while developing, change code below in Startup

        app.Map("/dashboard", frontendApp =>
        {
            frontendApp.UseSpa(spa =>
            {
                // To learn more about options for serving an Angular SPA from ASP.NET Core,
                // see https://go.microsoft.com/fwlink/?linkid=864501

                spa.Options.SourcePath = "ClientApp";

                if (env.IsDevelopment())
                {
                    spa.UseAngularCliServer(npmScript: "start --  --base-href=/frontend/ --serve-path=/ --live-reload-client=https://localhost:44302/frontend/sockjs-node/");
                }
            });
        });    


来源:https://stackoverflow.com/questions/51730535/my-spa-files-are-giving-404-errors-when-serving-the-spa-in-a-branch-of-the-reque

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!