ASP.NET Vue Hot Module Reloading using Vite

Hot module reloading is a must-have for improving the devops experience. No more convoluted webpack configs and plugins, it all works (mostly) out of the box with lightning fast HMR.

The GitHub repo has been updated to use Vite as the base, with a vue-cli branch for those that are using it.

The basic principle stands the same. During development .NET will run the npm serve command and merge the outputs into the console window. This command runs Vite bound to a different port, proxying the /api calls to .NET. The difference with Vite is that it handles the entire frontend, from the index.html to all the public path content. For deployment, Vite will build to the wwwroot path, which Visual Studio will copy to the final deploy location.

Setup

Create your ASP.NET application. To load the index.html file that Vite creates, add the following to your Program.cs file.

C#
app.UseDefaultFiles();

And add a test route to the Program.cs file.

C#
app.MapGet(u0022/api/testu0022, () =u003en{n  return u0022Hello World!u0022;n})

And as we will no longer be using it, remove the Index.cshtml file from the Pages folder.

To setup the frontend, create a “client” folder and npm init to initialise npm, then install the following npm packages.

npm i vite vue @vitejs/plugin-vue

Add the following scripts to your npm package.

JavaScript
u0022scriptsu0022: {n  u0022serveu0022: u0022viteu0022,n  u0022buildu0022: u0022vite buildu0022n}

Create a vite.config.js file next to the package.json file.

JavaScript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig(
  plugins: [vue()],
  root: './src',
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:5207' // Proxies to ASP.NET
      }
    },
  },
  build: {
    outDir: '../../wwwroot',
  }
})

Create a src folder with an index.html. This will act as the entry point for Vite.

HTML
<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="favicon.ico">
    <script type="module" src="./main.js"></script>
    </head>
    <body>
      <div id="app"></div>
  </body>
</html>

And a main.js file next to it. If you’re using TypeScript, this can be .ts files (and change the src above to “main.ts”).

JavaScript
import { createApp } from 'vue'
import App from './App.vue'
createApp(App)
  .mount('#app')

Add an App.vue file. The below is using Vue 3 setup composition syntax, but you can use the options API just as easily.

Vue
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
<template>
  <div id="app">
    <p>{{msg}}</p>
    <div><a href="/api/test">Test Route</a></div>
  </div>
</template>
<script setup>
import { ref } from 'vue'
const msg = ref('Welcome to Your Vue.js App')
</script>

Run your ASP.NET app, and npm run serve from within the “client” folder. Connect to http://localhost:3000 to view the Vite rendered frontend and visit the /api/test endpoint to view the .NET rendered backend.

Debugging

To automatically run the Vite server when the .NET project is debugged, at the following to your Program.cs file.

C#
// Run the serve command when running in development mode.
if (app.Environment.IsDevelopment())
{
    Process.Start(new ProcessStartInfo
    {
        FileName = "cmd",
        RedirectStandardInput = true,
        WorkingDirectory = Path.Combine(Environment.CurrentDirectory, "client")
    })!.StandardInput.WriteLine("npm run serve");
}

This will run the Vite serve command during development, with the output merged into the console. One thing to note is that the console will remain open when stopping the .NET server so keep an eye on your taskbar and shut down any orphaned Vite console windows.

Deployment

Vite will generate the frontend output into the wwwroot directory (deleting the contents if it already exists). Visual Studio can automate this building step with an msbuild config option.

In the Visual Studio file sidebar, double click on the project file to open it in a raw file view. Remove the following if it exists.

XML
<ItemGroup>
  <Content Remove="wwwrootindex.html" />
</ItemGroup>

And add the following in its place.

XML
<Target Name="PreBuild" BeforeTargets="PreBuildEvent" Condition="$(Configuration) == 'Release'">
  <Exec WorkingDirectory="client" Command="npm run build" />
</Target>

Hopefully this helps you in coupling ASP.NET and Vue. For a working solution, check out the GitHub repo.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *