-
Notifications
You must be signed in to change notification settings - Fork 736
Description
The Aspire team wants to make Aspire more friendly to client-side JavaScript developers. Today we have APIs such as AddNpmApp(...) and AddNodeApp(...). These are fairly thin wrappers around adding an executable.
What we would like to do is add an API which is more squarely targetted at the client-side developer. Let's walk through what we are thinking by looking at some code:
builder.AddClientsideJavaScriptApp("frontend")
.WithHttpEndpoint(env: "PORT")
.WithRestoreCommand("npm install")
.WithRunCommand("npm run dev")
.WithPublishCommand("npm run build", outputPath: "dist")
.WithHttpOtelCollector()
.WithEnvironmentPrefix("OTEL_", "VITE_OTEL_")
.WithEnvironment("BACKEND", api)
.WithReference(api, env: "BACKEND")
.WithReference(api, endpointName: "http", env: "BACKEND")
.PublishAsDockerfile()
.PublishAsNginx()
.PublishAsCaddyserver()
.PublishAsAzureBlobStorage(...);Lets look at each of these lines in a bit more detail:
builder.AddClientsideJavaScriptApp("frontend")
.WithRestoreCommand("npm install")
.WithRunCommand("npm run dev")
.WithPublishCommand("npm run build", outputPath: "dist")This would be a new resource (ClientsideJavaScriptResource) which derives from executable resource (so similar to Node/NPM resources in that respect). Its type would enable the use of the WithRunCommand(...), WithRestoreComand(...), and WithPublishCommand(...). This methods might hang off a common interface that we could use across different language ecosystems. For example we could do something similar with Python.
The effect of these methods in the dashboard is that the client-side JS resource would show the log output from invoking npm run dev. But there would be a child resource for the restore command. The parent resource would actually have a WaitForCompletion(...) on its child resource.
The publish command data would be stored in an annotation which is used by the code that publishes the app in the appropriate way (probably by creating a container image).
WithHttpOtelCollector(...)
.WithHttpOtelCollector(...)This would add an annotation on the resource that signals that when the dashboard launches it should expose not just gRPC, but also the http collector (we'll need to do work to support that in the dashboard - /cc @JamesNK). Its likely that the AddClientsideJavaScriptApp(...) implicitly calls this method, its shown here so we could discuss the need for it.
Environment variable prefixes
Many JavaScript tools use a prefixing mechanism to control a set of variables which are injected into the client-side code. For example Vite has a VITE_ prefix. We will add a method that allows us to find existing variables on the resource and remap them.
.WithEnvironmentPrefix("OTEL_", "VITE_OTEL_")This will probably need to be a specialized annotation that DCP supports so that it is always processed after all other environment variables have been generated.
Service discovery environment variables
We are having some debate on whether we should just get folks to use WithEnvironment("name", resource) - or whether we make some extensions to WithReference(...). There is a possibility of an NPM package which does service discovery integration. There will probably be a crawl-walk-run story here.
Publishing extensions
We want to make it easy to bundle up the client side JavaScript on a web server for deployment. We could have the following options:
.PublishAsDockerfile() // roll your own
.PublishAsNginx()
.PublishAsCaddyserver()
.PublishAsYarp()
.PublishAsAzureBlobStorage(...); // static CDN hosting scenariosMore detail to follow.