ASP.NET Core 2.1 中的 UseStaticFiles、UseSpaStaticFiles 和 UseSpa 有啥区别?

Posted

技术标签:

【中文标题】ASP.NET Core 2.1 中的 UseStaticFiles、UseSpaStaticFiles 和 UseSpa 有啥区别?【英文标题】:What is the difference between UseStaticFiles, UseSpaStaticFiles, and UseSpa in ASP.NET Core 2.1?ASP.NET Core 2.1 中的 UseStaticFiles、UseSpaStaticFiles 和 UseSpa 有什么区别? 【发布时间】:2019-09-23 01:50:37 【问题描述】:

ASP.NET Core 2.1.1 为 appBuilder 提供了几个看似相关的扩展方法:

UseStaticFiles 来自Microsoft.AspNetCore.StaticFiles UseSpaStaticFiles 来自Microsoft.AspNetCore.SpaServices.Extensions UseSpa 来自Microsoft.AspNetCore.SpaServices.Extensions

请帮助我理解他们的目的和彼此之间的关系?

另外,如果我以不同的顺序运行这些方法,从服务器执行的角度来看有什么不同

例如

app.UseStaticFiles() -> app.UseSpaStaticFiles() -> app.UseSpa()

app.UseSpa() -> app.UseSpaStaticFiles() -> app.UseStaticFiles()

【问题讨论】:

这些方法的“Spa”版本适用于单页应用程序。 @Darkonekt 你能详细说明一下吗?我知道SPA是什么。我不明白这些不同方法的具体内容是什么。 @IgorSoloydenko 我的回答解决了你的问题吗?如果是,请将我的答案标记为已接受的答案。 @NgôHùngPhúc 我仍然不确定...添加了一对澄清问题 【参考方案1】:

静态文件,例如 html、CSS、图像和 javascript,是一种资产 ASP.NET Core 应用程序直接服务于客户端。一些配置是 需要启用这些文件的服务。

UseStaticFiles - 在 Web 根目录(wwwroot 文件夹)内提供文件

UseSpaStaticFiles - 在资产中提供静态文件,如图像、css、js Angular 应用的文件夹

UseSpa - 让 asp.net 核心知道您要运行哪个目录 角度应用程序,在生产模式下运行时的 dist 文件夹和 哪个命令在开发模式下运行 Angular 应用程序

例子

services.AddSpaStaticFiles(configuration =>

 configuration.RootPath = "ClientApp/dist";
);

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");
    
);

【讨论】:

SPA 应用程序只是提供给客户端的静态文件。因此,如果我愿意,UseStaticFiles 应该足以提供 SPA 服务,对吧? UseSpaStaticFiles 的唯一“好处”是能够为 SPA 指定非 wwwroot 目录吗? 我认为你可以,但如果你使用 UseStaticFile 来切断 Spa 文件,你怎么能在开发模式下运行?可以在 prod 模式下运行,因为您可以指定文件夹路径。但是在使用 services.AddSpaStaticFile 的示例代码中,他们使用命令在 prod 模式下运行您的代码。否则,当您使用 UseStaticFile 时,您必须手动在视图中手动包含脚本标记 在我的场景中,我只会将 UseStaticFile 用于 prod 模式。对于开发模式,我正在运行一个简单的 bash 命令,例如 yarn start(带有 create-react-app)或带有内置 serve 目录的 serve... 我听到的是所有这些与 Spa 相关的方法都是真正只是方便的方法。 @IgorSoloydenko 是的。如果您使用 UseStaticFile,则必须在您的 cshtml 视图或页面中包含需要运行 Angular 应用程序的每个脚本标记。 AddSpaStaticFiles 或 UseSpa 让我们的生活更轻松 :)【参考方案2】:
    UseStaticFiles 提供来自 wwwroot 的文件,但可以更改。 UseSpaStaticFiles 做了类似的事情,但它需要注册 ISpaStaticFileProvider。如果 app.ApplicationServices.GetService() 返回 null,那么你会得到一个异常。
throw new InvalidOperationException($"To use nameof(UseSpaStaticFiles), you must " +
                    $"first register an nameof(ISpaStaticFileProvider) in the service provider, typically " +
                    $"by calling services.nameof(AddSpaStaticFiles).");

所以你需要调用app.AddSpaStaticFiles()来注册默认的ISaStaticFileProvider

    UseSpa 做了两件事。将所有请求重写到默认页面并尝试配置静态文件服务。与 UseSpaStaticFiles 不同,它不会抛出异常,而是退回到 wwwroot 文件夹。

实际上 UseSpaStaticFiles 和 UseSpa 都在内部调用相同的方法 UseSpaStaticFilesInternal 但第三个参数的值不同,即 allowFallbackOnServingWebRootFiles。这就是为什么 UseSpaStaticFiles 在没有注册 ISpaStaticFileProvider 时抛出异常的原因,它根本不允许回退到 wwwroot。

顺便说一句,如果 UseSpa 在内部回退到 wwwroot,它会调用旧的 app.UseStaticFiles(staticFileOptions);

github 资源链接: 1.SpaDefaultMiddleware 2.SpaStaticFilesExtensions

【讨论】:

所以理论上我可以摆脱 UseSpaStaticFiles 并单独使用 UseSpa 方法吗?我试过这个,但它只有在我同时使用 UseSpaStaticFiles 和 UseSpa 时才起作用......我发现它令人困惑......另外,如果 UseSpaStaticFiles 配置 spa 的输出文件夹以提供静态文件服务,那么为什么页面不加载,除非我调用 UseSpa ?对不起,我觉得这很混乱。 (使用netcore3.1) @ArunKumarA.J 如果您使用角度路由,第 3 点至关重要。需要将 Angular 使用的链接发送回 /index.html。当 UseSpa 对与端点不匹配的任何内容进行重写时,就会发生这种情况。

以上是关于ASP.NET Core 2.1 中的 UseStaticFiles、UseSpaStaticFiles 和 UseSpa 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

从asp.net core 2.1中的控制器访问BackgroundService

ViewData 未传递给 ASP.NET Core 2.1 中的布局

如何在 ASP.NET Core 2.1 中的计时器上运行 BackgroundService

ASP.NET Core 2.1 中的数据保护仅适用于一台机器

共享布局视图不适用于 ASP.NET Core 2.1 中的所有视图

ASP.NET Core 2.1 中的 Scaffold Identity UI 并添加全局过滤器