我正在尝试设置一个实验性的 C# 8 服务器,该服务器可以运行 Web API、Razor 页面,还可以运行特定路径(例如“/spa1”)之外的各种 React 应用程序,但无法让 SPA 在路径之外提供服务。根据我在下面列出的一些相关堆栈溢出问题(以及其他一些问题)中读到的内容,这应该可行。
*注:我的客户端目录是
{SolutionFolder}\projects\cs.web.client
,Web 服务器是 {SolutionFolder}\projects\CS.Web.Server
public static class SpaApplicationBuilderExtensions
{
public static void EnableReactApp(this WebApplication app, string spaPath, string codePath, int serverPort, bool isDev = false)
{
ArgumentNullException.ThrowIfNull(app);
ArgumentException.ThrowIfNullOrEmpty(spaPath);
ArgumentException.ThrowIfNullOrEmpty(codePath);
app.Map(new PathString(spaPath), client =>
{
client.UsePathBase(new PathString(spaPath));
//client.UseSpaStaticFiles();
client.UseSpa(spa =>
{
var path = Path.Combine((Directory.GetParent(Directory.GetCurrentDirectory()))?.FullName ?? string.Empty, codePath);
spa.Options.SourcePath = path;
spa.Options.DefaultPageStaticFileOptions = new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(path)
{
UseActivePolling = true,
},
RedirectToAppendTrailingSlash = true,
};
if (isDev)
{
spa.Options.DevServerPort = serverPort;
spa.UseReactDevelopmentServer("dev");
}
});
});
}
}
程序.CS
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
IMvcBuilder? views = builder.Services.AddControllersWithViews();
IMvcBuilder? pages = builder.Services.AddRazorPages();
#if (DEBUG)
views.AddRazorRuntimeCompilation();
pages.AddRazorRuntimeCompilation();
#endif
var app = builder.Build();
app.UseStaticFiles();
app.UseHttpsRedirection();
app.UseRouting();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.MapControllers();
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.EnableReactApp("/spa1", "cs.web.client", 707, app.Environment.IsDevelopment());
app.Run();
而且,事实上,当我运行这个时,我可以看到 vite 正在
https://localhost:707
为 React 应用程序提供服务,这是它应该做的。但是,当我转到 https://localhost:7788/spa1
时,我收到此错误消息:TimeoutException: The create-react-app server did not start listening for requests within the timeout period of 120 seconds. Check the log output for error information.
我的 Razor 页面和其他 API 端点工作正常。
我一直在看的相关问题:
我还尝试研究模板正在做什么,以确保我做得正确,但是想要将
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"
添加到启动配置文件中的环境变量中,这需要所有设置都位于 csproj 文件中,并且这似乎没有办法让你将其设置为特定路径,我也无法运行多个 SPA。
这是我的
vite.config.ts
const baseFolder = env.APPDATA !== undefined && env.APPDATA !== ''
? `${env.APPDATA}/ASP.NET/https`
: `${env.HOME}/.aspnet/https`;
const certificateName = "cs.web.client";
const certFilePath = path.join(baseFolder, `${certificateName}.pem`);
const keyFilePath = path.join(baseFolder, `${certificateName}.key`);
if (!fs.existsSync(certFilePath) || !fs.existsSync(keyFilePath)) {
if (0 !== child_process.spawnSync('dotnet', [
'dev-certs',
'https',
'--export-path',
certFilePath,
'--format',
'Pem',
'--no-password',
], { stdio: 'inherit', }).status) {
throw new Error("Could not create certificate.");
}
}
const target = env.ASPNETCORE_HTTPS_PORT ? `https://localhost:${env.ASPNETCORE_HTTPS_PORT}` :
env.ASPNETCORE_URLS ? env.ASPNETCORE_URLS.split(';')[0] : 'http://localhost:7788';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [plugin()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
server: {
proxy: {
'^/weatherforecast': {
target,
secure: false
},
},
port: 707,
https: {
key: fs.readFileSync(keyFilePath),
cert: fs.readFileSync(certFilePath),
}
}
})
谢谢!
尝试添加回退端点,这会告诉主机(在本例中为 .net 应用程序)对于 razor 页面中未定义的路径回退到
/reactapp
。
public static class SpaApplicationBuilderExtensions
{
public static void EnableReactApp(this WebApplication app, string spaPath)
{
ArgumentNullException.ThrowIfNull(app);
ArgumentException.ThrowIfNullOrEmpty(spaPath);
ArgumentException.ThrowIfNullOrEmpty(codePath);
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapFallbackToPage(spaPath);
});
}
}
然后创建一个传递到反应应用程序的页面,其名称类似于您的路径
spa1.cshtml
:
@page
@{
Layout = null;
ViewData["Title"] = "React App";
}
@* Entry point for our react app *@
@* The id is the same as the one that react references in index.tsx *@
<div id="react-app"></div>
<environment names="Development">
<script src="~/vite.config.ts"></script>
</environment>
<environment names="Staging,Production">
<script src="~/vite.config.ts" asp-append-version="true"></script>
</environment>
如果运行,您的 React 应用程序将在放置
<div id="react-app"></div>
的位置进行渲染。