我有一个股票aspnetcore
和reactjs
应用程序,该应用程序是通过启动模板(dotnet new react
)生成的。我希望从根URL的子路径中提供SPA应用程序;例如而不是示例应用https://localhost:5001/counter
,我正在寻找可以从https://localhost:5001/myapp/counter
投放的示例应用。
我将Startup.cs
更改为:
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
对此:
app.Map(new Microsoft.AspNetCore.Http.PathString("/myapp"), appMember =>
{
appMember.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
});
这类作品。如果我浏览到https://localhost:5001/myapp/
,它似乎正在加载index.html,但是静态文件正在尝试从根路径而非子路径进行加载。
需要进行哪些更改,以使React应用程序将子路径用作根目录?我希望它既可以在交互式VS开发环境中工作,又可以在IIS上部署时工作。好像已经接近了,但是我想念一些东西。
此处提供解决方案的示例演示:https://github.com/petertirrell/mvc-spa-demo/tree/master/mvc-spa-demo
谢谢!
答案 0 :(得分:2)
通过将其添加到package.json顶部,开始将应用移动到子路径:
"homepage": "/myapp/",
在ClientApp文件夹中运行npm start
时,应用正在提供http://localhost:3000/myapp
然后像这样更改Startup.cs
:
先删除
app.UseSpaStaticFiles()
然后添加
const string spaPath = "/myapp";
if (env.IsDevelopment())
{
app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments(spaPath)
|| ctx.Request.Path.StartsWithSegments("/sockjs-node"),
client =>
{
client.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
spa.UseReactDevelopmentServer(npmScript: "start");
});
});
}
else
{
app.Map(new PathString(spaPath), client =>
{
// `https://github.com/dotnet/aspnetcore/issues/3147`
client.UseSpaStaticFiles(new StaticFileOptions()
{
OnPrepareResponse = ctx =>
{
if (ctx.Context.Request.Path.StartsWithSegments($"{spaPath}/static"))
{
// Cache all static resources for 1 year (versioned file names)
var headers = ctx.Context.Response.GetTypedHeaders();
headers.CacheControl = new CacheControlHeaderValue
{
Public = true,
MaxAge = TimeSpan.FromDays(365)
};
}
else
{
// Do not cache explicit `/index.html` or any other files. See also: `DefaultPageStaticFileOptions` below for implicit "/index.html"
var headers = ctx.Context.Response.GetTypedHeaders();
headers.CacheControl = new CacheControlHeaderValue
{
Public = true,
MaxAge = TimeSpan.FromDays(0)
};
}
}
});
client.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
spa.Options.DefaultPageStaticFileOptions = new StaticFileOptions()
{
OnPrepareResponse = ctx => {
// Do not cache implicit `/index.html`. See also: `UseSpaStaticFiles` above
var headers = ctx.Context.Response.GetTypedHeaders();
headers.CacheControl = new CacheControlHeaderValue
{
Public = true,
MaxAge = TimeSpan.FromDays(0)
};
}
};
});
});
}
别忘了在第一次测试更改之前清除浏览器历史记录,例如Azure。
答案 1 :(得分:1)
您可以通过以下方式实现:
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/build";
});
在您的ConfigureServices
中:
string spaPath = "/myapp";
if (env.IsDevelopment())
{
app.MapWhen(y => y.Request.Path.StartsWithSegments(spaPath), client =>
{
client.UseSpa(spa =>
{
spa.UseReactDevelopmentServer(npmScript: "start");
});
});
}
else
{
app.Map(new PathString(spaPath), client =>
{
client.UseSpaStaticFiles();
client.UseSpa(spa => {});
});
}
请注意,在开发中我们使用.MapWhen
,因为.Map
会导致您的静态文件在/myapp/myapp/[file]
而不是/myapp/[file]
上可用。
答案 2 :(得分:0)
您可以通过在静态文件选项中指定RequestPath来实现。下面的代码可能对您有用
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "Client")),
RequestPath = "/client"
});
}
答案 3 :(得分:0)
我结合了每个答案中的一些以使其正常工作。您需要将 "homepage": "/myapp"
添加到 package.json
并将配置更改为 Startup.cs
。我使用了 Shoe's answer 中提供的更简单的配置,没有所有额外的缓存和套接字指令,因为我不需要这些。
因为我的应用程序还使用了 React Router 作为 /myapp
下的 SPA 路由,所以我还需要将 basename
添加到根 BrowserRouter
:
<BrowserRouter basename="/myapp" >...</BrowserRouter>