I am working on an ASP.NET Core non-spa project in frontend part, which is mixed with backend. What I need, that just start webpack-dev-server (or other npm script, which will watching), when I am building and starting the project. I will serve only js, css, assets, but no html, because there is Razor with .cshtml
Now I am using:
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
spa.UseReactDevelopmentServer(npmScript: "start");
});
for solving my problem, and it works somehow, but I don't understand why I need use this.
Why is there is no useDevelopmentServer
or useNodeCommand
or something like that?
I just need to use all possibilities of modern development in the non-spa project, before our clients will decide to move to SPA.
Of course I can start manually my npm (or yarn or whatever else) from terminal, but I need automation of process, because it's hard to explain our backenders how to do that, and because it's convenient.
We can implement it by using middleware, and we should let this npm script is run only once. Here is my sample middleware.
NpmMiddleware.cs
public class NpmMiddleware
{
private static bool _npmScriptStarted = false;
private readonly RequestDelegate _next;
private readonly string _sourcePath;
private readonly string _npmScript;
public NpmMiddleware(RequestDelegate next, string sourcePath, string npmScript)
{
_next = next;
_sourcePath = sourcePath;
_npmScript = npmScript;
}
public async Task InvokeAsync(HttpContext context)
{
if (!_npmScriptStarted)
{
var isDevelopment = string.Equals(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"), "Development", StringComparison.OrdinalIgnoreCase);
if (isDevelopment)
{
var npmScriptProcess = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "npm",
Arguments = $"run {_npmScript}",
RedirectStandardError = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
WorkingDirectory = _sourcePath
}
};
npmScriptProcess.Start();
_npmScriptStarted = true;
}
}
// Call the next delegate/middleware in the pipeline
await _next(context);
}
}
public static class NpmMiddlewareExtensions
{
public static IApplicationBuilder UseNpmScript(this IApplicationBuilder builder, string sourcePath, string npmScript)
{
return builder.UseMiddleware<NpmMiddleware>(sourcePath, npmScript);
}
}
And use it in Program.cs(or startup.cs file if you have) file.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// ... other middlewares ...
app.UseNpmScript("ClientApp", "start");
// ... remaining configuration ...
}