Search code examples
reactjsasp.netasp.net-mvcasp.net-corevite

React Preamble error when trying to serve files through Vite dev server to ASP.NET Project


I'm trying to set up an ASP.NET MVC application with a ClientApp that uses React with Vite as the bundler. This is meant to be an MPA instead of a SPA, so there will be a separate .tsx file for each page of my application (i.e. home.tsx, about.tsx, etc.)

During development, the ClientApp files should be served by the Vite development server to my ASP.NET app for HMR, while in production the app will use the bundled files within wwwroot/dist.

I've attempted to set up my Program.cs to communicate with the Vite development server using the Vite.AspNetCore package.

Program.cs:

using Vite.AspNetCore.Extensions;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddViteServices(options =>
{
    options.PackageDirectory = "ClientApp"; // Set the root path to the ClientApp folder
});

builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}
else
{
    app.UseViteDevelopmentServer();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

In order to read from the Vite development server, I've added the following block to my _Layout.cshtml file that will be shared by all my views:

<environment include="Development">
    <script type="module" src="https://localhost:5173/@@vite/client"></script>
    <link rel="stylesheet" href="https://localhost:5173/src/theme/site.css" />
    @if (ViewData["ViteScript"] != null)
    {
        <script defer type="module" src="@($"https://localhost:5173/src/pages/{ViewData["ViteScript"]}/index.tsx")"></script>
    }
</environment>

In other words, I'm trying to read the site.css file from ClientApp/src/theme/site.css, and the index.tsx file that's associated with the particular page I'm on, like ClientApp/src/pages/home/index.tsx. The name of the page (like "home") is stored in the ViewData["ViteScript"] at the top of the Razer view.

So I run my Vite development server on port 5173 and then I run my ASP.NET app, but I'm met with the generic message:

"Uncaught Error: @vitejs/plugin-react can't detect preamble. Something is wrong."

For reference, here is my vite.config.ts file:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import mkcert from "vite-plugin-mkcert";
import appsettings from "../appsettings.json";
import appsettingsDev from "../appsettings.Development.json";

const cssPattern = /\.css$/;
const imagePattern = /\.(png|jpe?g|gif|svg|webp|avif)$/;

export default defineConfig({
  plugins: [react(), mkcert()],
  build: {
    manifest: appsettings.Vite.Manifest,
    outDir: "../wwwroot/dist",
    emptyOutDir: true,
    rollupOptions: {
      input: {
        home: "./src/pages/home/index.tsx",
        site: "./src/site.ts",
        styles: "./src/theme/site.css",
      },
      output: {
        entryFileNames: "js/[name].js",
        chunkFileNames: "js/[name]-chunk.js",
        assetFileNames: (info) => {
          if (info.name) {
            if (cssPattern.test(info.name)) {
              return "css/[name][extname]";
            }
            if (imagePattern.test(info.name)) {
              return "images/[name][extname]";
            }

            return "assets/[name][extname]";
          } else {
            return "[name][extname]";
          }
        },
      },
    },
  },
  server: {
    port: appsettingsDev.Vite.Server.Port,
    strictPort: true,
    hmr: {
      host: "localhost",
      clientPort: appsettingsDev.Vite.Server.Port,
    },
  },
});

When I check the Sources tab of the Chrome Developer Tools, I see the ASP.NET app running on localhost:44380 and the Vite dev server running on localhost:5173 (and its files like ExampleComponent.tsx and pages/home/index.tsx.

Sources tab

Here's a screenshot of my ClientApp within the Solution Explorer:

ClientApp folder

If anyone has experienced a similar issue when trying to integrate the Vite development server into an MPA, I'd appreciate your help.

Thanks!


Solution

  • You also need to add the react-refresh script to make the development server work with React. You can see it in the Backend Integration page.

    Make sure you add it before the @vite/client script.