Webpack Proxy Configuration for .NET Core 3 SPA Projects

Webpack Proxy Configuration for .NET Core 3 SPA Projects

On August 5th of 2019, Daniel Roth announced on the aspnetcore repository that Microsoft.AspNetCore.SpaServices and Microsoft.AspNetCore.NodeServices were being made obsolete in the coming .NET Core 3 release.

As you can see from the annourncement issue, there has been quite a bit of commentary from folks who have been relying on these services for various workflows.

I have been using the DevelopmentServer middleware quite heavily in my Bivrost project for debugging purposes. The way it worked in .NET Core 2 is the middeware would shell out and start a webpack development server and proxy requests from the aspnetcore application to the SPA application.

This functionalty went away. So I had to figure out another way to setup my development workflow.

Workaround for Webpack Based Frontend Apps

This workaround is taken directly from this application that I work on in my spare time. I have removed all use of the SpaServices provided development server. Instead, I configure webpack to proxy requests to aspnetcore and setup vscode to launch both processes.

Startup.cs

The startup configuration is here only to serve up the built webpack based SPA application for production purposes. The location of this path is configurable in the appsettings.json and is specific to your application.

public class Startup
  {
    public void ConfigureServices(IServiceCollection services)
    {
      //configures the root of the built spa files
      services.AddSpaStaticFiles(configuration =>
      {
          configuration.RootPath = Configuration["Client"];
      });
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
      //tells the application to serve them up for production use
      app.UseStaticFiles();
      app.UseSpaStaticFiles();
    }
  }

vue.config.js || webpack.config.js

This configuration can go in your vue.config.js or webpack.config.js. It will proxy all http requests to the provided url (including websockets/signalr). This is a fairly standard thing to do in the frontend world.

module.exports = {
  devServer: {
    proxy: 'http://localhost:5000/'
  }
};

.vscode/launch.json

The vscode launch.json tells the editor how to launch your application for debugging. This setup creates 2 configurations a Client for starting the webpack based app using NPM and a Server for starting the backend using dotnet cli. Then I use a compound configuration that joins the two together. Simply select the compound configuration in vscode and click run.

Screen Shot 2020-02-29 at 12 05 37 PM

Note: The Client configuration does not attempt to connect a debugger, it just starts the app via NPM. I prefer to debug client-side code in my browser.

{
  "version": "0.2.0",
  "compounds": [
    {
      "name": "Bivrost",
      "configurations": ["Server", "Client"]
    }
  ],
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Client",
      "runtimeExecutable": "npm",
      "runtimeArgs": [
        "run-script",
        "serve"
      ],
      "noDebug":true,
      "cwd": "${workspaceFolder}/src/client",
      "skipFiles": [
        "<node_internals>/**"
      ]
    },
    {
      "name": "Server",
      "type": "coreclr",
      "request": "launch",
      "preLaunchTask": "build",
      // If you have changed target frameworks, make sure to update the program path.
      "program": "${workspaceFolder}/src/server/bin/Debug/netcoreapp3.1/server.dll",
      "args": [],
      "cwd": "${workspaceFolder}/src/server",
      "stopAtEntry": false,
      "env": {
          "ASPNETCORE_ENVIRONMENT": "Development",
      }
    }
  ]
}

When the application is running in debug, your screen will look similar to this:

Screen Shot 2020-02-29 at 12 07 03 PM

Note: There are two debug consoles one for the Client app and one for the Server app. You also have a drop-down menu in the debug controls at the top to select either process as well. You do have to stop them both.

Follow me on Mastodon!