Adding a Qwik project to .NET Aspire

Make sure you have the latest .NET SDK and Visual Studio 2022 Preview installed.

.NET SDK

Visual Studio 2022 Preview

From the visual studio installer install .NET Aspire SDK (Preview).

Modify -> Individual Components -> .NET Aspire SDK (Preview)

Visual Studio Individual Components Installer Window

Create a new .NET Aspire Starter Application

Using Visual Studio to Create a .NET Aspire Starter Application 

The starter template should look like the following.

Solution Explorer

Right click on the AppHost project (e.g. SampleAspireApp.AppHost) and click Manage NuGet packages... . Go to the updates tab and check the Include prerelease checkbox. Update to the latest Aspire Hosting package.

NuGet Package Manager

Time to bootstrap a Qwik application. From the terminal change your directory to the created Aspire project.

Use the following command to create a  Qwik project,

npm create qwik@latest

Type in the directory name under which the project files will reside.

Installing Qwik using Windows Terminal

Add a Dockerfile to the Qwik project,

FROM node:20.7

WORKDIR /app

COPY package.json package.json
COPY package-lock.json package-lock.json

RUN npm i

COPY . .

EXPOSE 5173

CMD [ "npm", "start" ]
Dockerfile

Also add a .env file containing the following environment variable that points to the Aspire ApiService project running on the Docker container.

PUBLIC_QWIK_APP_WEATHER_API=$services__apiservice__1

Go back to the AppHost project and add the following to your Program.cs file

builder.AddNpmApp("qwik", "../SampleAspireApp.Spa")
    .WithReference(apiservice)
    .WithServiceBinding(containerPort: 5173, scheme: "http", env: "PORT")
    .AsDockerfileInManifest();

AddNpmApp takes two arguments, first argument is the name of the node project and the second one is the project path to your node project. The container port is set to 5173 means the Qwik app will be hosted on http://localhost:5173.

The final Program.cs file should look like this,

var builder = DistributedApplication.CreateBuilder(args);

var cache = builder.AddRedisContainer("cache");

var apiservice = builder.AddProject<Projects.SampleAspireApp_ApiService>("apiservice");

builder.AddProject<Projects.SampleAspireApp_Web>("webfrontend")
    .WithReference(cache)
    .WithReference(apiservice);

builder.AddNpmApp("qwik", "../SampleAspireApp.Spa")
    .WithReference(apiservice)
    .WithServiceBinding(containerPort: 5173, scheme: "http", env: "PORT")
    .AsDockerfileInManifest();

builder.Build().Run();
Program.cs

And done, Run the Aspire project and two browser window should pop up.

Aspire Dashboard
Qwik Application

Let's fetch the forcast from the ApiService and show it in the UI. Add the following to the index.tsx file.

import { Resource, component$, useResource$ } from "@builder.io/qwik";
import type { DocumentHead } from "@builder.io/qwik-city";

export default component$(() => {
  const forecast = useResource$<Forecast[]>(async () => {
    const response = await fetch(
      `${import.meta.env.PUBLIC_QWIK_APP_WEATHER_API}/weatherforecast`
    );
    const data = await response.json();
    return data as Forecast[];
  });

  return (
    <>
      <Resource
        value={forecast}
        onPending={() => <p>Loading...</p>}
        onResolved={(forecast: Forecast[]) => <table>
          <thead>
            <tr>
              <th>Date</th>
              <th>Temp. (C)</th>
              <th>Temp. (F)</th>
              <th>Summary</th>
            </tr>
          </thead>
          <tbody>
            {forecast.map((f: Forecast, i: number) => {
              return (
                <tr key={i}>
                  <td>{f.date}</td>
                  <td>{f.temperatureC}</td>
                  <td>{f.temperatureF}</td>
                  <td>{f.summary}</td>
                </tr>
              );
            })}
          </tbody>
        </table>}
      />
    </>
  );
});

type Forecast = {
  date: string;
  temperatureC: number;
  temperatureF: number;
  summary: string;
}

export const head: DocumentHead = {
  title: "Welcome to Qwik",
  meta: [
    {
      name: "description",
      content: "Qwik site description",
    },
  ],
};
index.tsx

The app should show the forecast in a styled table like the following,

Forecast Table

Repository

QwikAspire

Aspire Samples

.NET Aspire Overview