How commands work
Not everything a deploy needs happens in a cloud. A frontend has to be built before it’s uploaded. Code generation has to run before a bundle that imports it. A dev server has to be running while you develop. Command puts those local processes into your Stack, as resources, so they run in the right order and only when they need to.
A build runs before the site that uploads its output. An exec runs before what depends on its effects. A dev server runs only under alchemy dev.
Builds produce an asset
Section titled “Builds produce an asset”A build runs a command that writes an output directory, like npm run build writing dist. The directory is the build’s result, and other resources take it as an input:
const build = yield* Command.Build("vite-build", { command: "npm run build", cwd: "./frontend", outdir: "dist" });The output’s hash is recorded too, so whatever uploads it knows when the files actually changed.
Execs run for their effects
Section titled “Execs run for their effects”An exec runs a command for what it does, not what it writes: generate code, seed a database, call a script. It succeeds when the command exits with code 0.
yield* Command.Exec("codegen", { command: "npm run codegen", cwd: "./packages/api" });Destroying an exec doesn’t undo what it did.
Dev servers run while you develop
Section titled “Dev servers run while you develop”A dev server is a long-running process, like vite dev, that runs for as long as alchemy dev does. Its url is read from the process’s output, and other resources can use it. During alchemy deploy, it does nothing.
See Dev servers.
Memoization: running only when needed
Section titled “Memoization: running only when needed”A build or exec runs again only when something it depends on changed. Its inputs, the files under its working directory, are hashed, along with its command and environment. Unchanged inputs mean no run, so a deploy that touched only the backend never rebuilds the frontend.
See Memoization.
How Command fits in a Stack
Section titled “How Command fits in a Stack”Commands are resources with no cloud and no credentials. Command.providers() is already part of AWS.providers() and Cloudflare.providers(), and the Website resources on every cloud use builds and dev servers underneath. Declare one yourself for any local step the deploy depends on.