{"id":385,"date":"2026-04-21T10:00:00","date_gmt":"2026-04-21T17:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/aspire\/?p=385"},"modified":"2026-04-21T08:37:55","modified_gmt":"2026-04-21T15:37:55","slug":"aspire-bun-support-and-container-enhancements","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/aspire\/aspire-bun-support-and-container-enhancements\/","title":{"rendered":"Aspire 13.2: Bun Support and Container Enhancements"},"content":{"rendered":"<p>If you&#8217;ve been following the <a href=\"https:\/\/aspire.dev\/integrations\/frameworks\/javascript\/\">JavaScript story in Aspire<\/a>, 13.2 is the kind of release you want to see. Focused, deliberate, and packed with improvements that make a real difference.<\/p>\n<p>Bun support lands for Vite apps. Yarn gets more reliable. Container publishing becomes more predictable. And a handful of debugging and build improvements add up to a noticeably smoother experience.<\/p>\n<p>In other words: better tooling, more building.<\/p>\n<p><div class=\"alert alert-primary\"><p class=\"alert-divider\"><i class=\"fabric-icon fabric-icon--Info\"><\/i><strong>Note<\/strong><\/p>To keep this post aligned with the JavaScript thread, the code samples use <code>apphost.ts<\/code>. If you&#8217;d rather author your AppHost in <code>AppHost.cs<\/code>, the linked aspire.dev docs include C# examples for the same patterns.<\/div><\/p>\n<h2>\u26a1 Bun support for Vite apps<\/h2>\n<p>Let&#8217;s start with the headline. Bun is now a first-class option for <a href=\"https:\/\/aspire.dev\/integrations\/frameworks\/javascript\/#use-bun\">Vite apps in Aspire<\/a>.<\/p>\n<pre><code class=\"language-ts\">import { createBuilder } from '.\/.modules\/aspire.js';\n\n\/\/ The builder pattern is used to add resources and model their relationship\nconst builder = await createBuilder();\n\n\/\/ We're adding a Vite app, that points to our frontend directory...\n\/\/ We chain a call to `withBun` to imply that we want the frontend \n\/\/ resource to use bun as its package manager.\nawait builder\n  .addViteApp(\"frontend\", \".\/frontend\")\n  .withBun();\n\nawait builder.build().run();<\/code><\/pre>\n<p>That is refreshingly clean. Call <a href=\"https:\/\/aspire.dev\/integrations\/frameworks\/javascript\/#use-bun\"><code>withBun()<\/code><\/a>, and Aspire knows how to treat your <a href=\"https:\/\/aspire.dev\/integrations\/frameworks\/javascript\/#add-vite-application\"><code>addViteApp()<\/code> resource<\/a> like a Bun-backed app instead of assuming <code>npm<\/code>. No ceremony. No configuration scavenger hunt. Just a single fluent call that works.<\/p>\n<p>Why does this matter? Because Bun is fast, and JavaScript developers tend to notice when tooling is slow.<\/p>\n<ul>\n<li>Startup time matters.<\/li>\n<li>Install time matters.<\/li>\n<li>Feedback loops matter.<\/li>\n<\/ul>\n<p>If your team already likes Bun, Aspire no longer makes you feel like you&#8217;re coloring outside the lines.<\/p>\n<p>And if you don&#8217;t use Bun? Fine. npm, Yarn, and pnpm still work. This isn&#8217;t Aspire picking favorites. It&#8217;s Aspire behaving like the JavaScript ecosystem exists in the real world.<\/p>\n<h3><code>withYarn()<\/code> got more reliable too<\/h3>\n<p>Bun is the shiny headline, but Yarn users get something arguably even more important: fewer headaches. Aspire 13.2 improves reliability for <a href=\"https:\/\/aspire.dev\/integrations\/frameworks\/javascript\/#use-yarn\"><code>withYarn()<\/code><\/a> with <a href=\"https:\/\/aspire.dev\/integrations\/frameworks\/javascript\/#add-vite-application\"><code>addViteApp()<\/code><\/a>, which is the sort of fix that sounds small right up until it saves you twenty minutes of local dev confusion.<\/p>\n<p>Reliability is a feature in its own right, and this improvement delivers exactly that.<\/p>\n<p>And if your team is still on Yarn, the TypeScript AppHost version stays just as simple:<\/p>\n<pre><code class=\"language-ts\">await builder.addViteApp(\"frontend\", \".\/frontend\")\n  .withYarn();<\/code><\/pre>\n<h2>\ud83d\udc33 Container changes that actually help<\/h2>\n<p>There are also some genuinely useful <a href=\"https:\/\/aspire.dev\/whats-new\/aspire-13-2\/#docker-and-container-enhancements\">container improvements in 13.2<\/a> that give you more control and predictability exactly where you need them.<\/p>\n<h3>Pull policy is now explicit<\/h3>\n<p>If you&#8217;re working with Docker Compose publishing, <a href=\"https:\/\/aspire.dev\/reference\/api\/typescript\/aspire.hosting\/imagepullpolicy\/\"><code>PullPolicy<\/code><\/a> is now a proper setting, including a <code>Never<\/code> option for &#8220;use the local image and do not get creative&#8221; workflows.<\/p>\n<p>That&#8217;s useful when you&#8217;re iterating locally, testing freshly built images, or working in an environment where pulling from a registry is the wrong move. It&#8217;s a small change, but it makes container behavior more honest and easier to reason about.<\/p>\n<p>Imagine you&#8217;re working in your TypeScript AppHost, and you&#8217;ve already added docker compose support:<\/p>\n<pre><code class=\"language-bash\">aspire add docker<\/code><\/pre>\n<p>You can now add an import for the <code>ImagePullPolicy<\/code> enum and chain a call to <a href=\"https:\/\/aspire.dev\/reference\/api\/typescript\/aspire.hosting\/containerresource\/withimagepullpolicy\/\"><code>withImagePullPolicy<\/code><\/a>.<\/p>\n<pre><code class=\"language-ts\">import { createBuilder, ImagePullPolicy } from '.\/.modules\/aspire.js';\n\nconst builder = await createBuilder();\n\n\/\/ Adds a Docker Compose publishing environment.\nawait builder.addDockerComposeEnvironment(\"compose\");\n\n\/\/ Add a container based on the myorg\/worker:latest image.\n\/\/ Specify that the image should never be pulled from the registry.\nconst worker = await builder.addContainer(\"worker\", \"myorg\/worker:latest\")\n  .withImagePullPolicy(ImagePullPolicy.Never);\n\nawait builder.build().run();<\/code><\/pre>\n<p>If that reads like &#8220;please use the image I already built and leave the registry out of it,&#8221; that&#8217;s because it is. The <a href=\"https:\/\/aspire.dev\/deployment\/docker-compose\/#image-pull-policy\">Docker Compose deployment docs<\/a> spell out the same mapping directly.<\/p>\n<h3>PostgreSQL 18+ just works<\/h3>\n<p>PostgreSQL 18 changed its internal data directory layout. Naturally, that means volume mapping got weird.<\/p>\n<p>Aspire 13.2 now handles the data volume path correctly for PostgreSQL 18 and later. If you&#8217;re running newer Postgres versions, persistence keeps working seamlessly with no extra configuration required.<\/p>\n<pre><code class=\"language-ts\">import { createBuilder } from '.\/.modules\/aspire.js';\n\nconst builder = await createBuilder();\n\n\/\/ Add a postgres server resource with a data volume.\nconst postgres = await builder.addPostgres(\"postgres\")\n  .withDataVolume({ isReadOnly: false });\n\n\/\/ From the postgres server resource add a database named 'appdb'\nconst appDb = await postgres.addDatabase(\"appdb\");\n\n\/\/ Add a node app for our api and reference the database.\nawait builder\n  .addNodeApp(\"api\", \".\/api\", \"src\/index.ts\")\n  .withReference(appDb)\n  .waitFor(postgres);\n\nawait builder.build().run();<\/code><\/pre>\n<p>So if you&#8217;re attaching a durable volume to local Postgres, 13.2 handles it correctly out of the box. The <a href=\"https:\/\/aspire.dev\/integrations\/databases\/postgres\/postgres-host\/#add-postgresql-server-resource-with-data-volume\">PostgreSQL hosting docs<\/a> show the same pattern in both TypeScript and C#.<\/p>\n<p>That&#8217;s exactly the kind of solid platform support that keeps development moving.<\/p>\n<h2>\ud83d\udc1b Better debugging and fewer build paper cuts<\/h2>\n<p>13&#46;2 also ships a set of quality-of-life improvements to day-to-day development, particularly around <a href=\"https:\/\/aspire.dev\/whats-new\/aspire-13-2\/#enhanced-debugging-experience\">debugging<\/a> and <a href=\"https:\/\/aspire.dev\/whats-new\/aspire-13-2\/#build-improvements\">builds<\/a>.<\/p>\n<h3>Better debugger displays<\/h3>\n<p>Core Aspire types now use <code>DebuggerDisplayAttribute<\/code>, so stepping through an AppHost is less of a scavenger hunt. You get clearer values for things like <code>DistributedApplication<\/code>, resources, and endpoint expressions instead of drilling into objects just to figure out what you&#8217;re looking at.<\/p>\n<h3>Better <code>WaitFor<\/code> failures and event behavior<\/h3>\n<p>When resources fail to start, the messages around <a href=\"https:\/\/aspire.dev\/whats-new\/aspire-13-2\/#resource-event-improvements\"><code>WaitFor<\/code><\/a> are more helpful. That&#8217;s good.<\/p>\n<p><code>BeforeResourceStartedEvent<\/code> also now fires only when a resource is actually starting, which is even better. Less noise. Better signal. More predictable behavior.<\/p>\n<h3><code>launchSettings.json<\/code> is less fragile now<\/h3>\n<p>Aspire now accepts comments and trailing commas in <a href=\"https:\/\/aspire.dev\/whats-new\/aspire-13-2\/#build-improvements\"><code>launchSettings.json<\/code><\/a>.<\/p>\n<p>This is a welcome improvement. Real developers leave trailing commas and add comments to explain why a setting exists, and now Aspire handles that gracefully, just as you&#8217;d expect.<\/p>\n<h3><code>GenerateAssemblyInfo<\/code> no longer gets in the way<\/h3>\n<p>If your AppHost disables <code>GenerateAssemblyInfo<\/code>, 13.2 now behaves correctly without requiring any workarounds. Another solid improvement to build reliability.<\/p>\n<h2>\ud83c\udf10 The bigger JavaScript picture<\/h2>\n<p>What I like about this release is that it keeps pushing the same idea forward: <a href=\"https:\/\/aspire.dev\/integrations\/frameworks\/javascript\/\">JavaScript support in Aspire<\/a> isn&#8217;t a novelty feature.<\/p>\n<p>This is what platform maturity looks like. Thoughtful, confident progress that makes polyglot development feel natural and productive.<\/p>\n<p>If you&#8217;re using C# as the orchestration layer and JavaScript for the parts that are best written in JavaScript, Aspire keeps getting better at supporting you exactly where you are. That&#8217;s the goal.<\/p>\n<h2>\ud83c\udf89 The bottom line<\/h2>\n<p>Aspire 13.2 doesn&#8217;t reinvent the JavaScript story. It sharpens it.<\/p>\n<p>Bun is now a first-class option for Vite apps. Yarn is more reliable. Containers are more predictable. Debugging is nicer. Build reliability is stronger. Each improvement is purposeful, and together they make the experience feel cohesive and polished.<\/p>\n<p>That&#8217;s what great releases look like: consistent forward momentum, where the tooling does the right thing and development flows without interruption.<\/p>\n<h2>Get involved<\/h2>\n<ul>\n<li><strong>\ud83d\udcd6 Learn more:<\/strong> Read the docs on <a href=\"https:\/\/aspire.dev\/integrations\/frameworks\/javascript\/#use-bun\">using Bun with the Official JavaScript integration<\/a> and the broader <a href=\"https:\/\/aspire.dev\/integrations\/frameworks\/bun-apps\/\">Community Toolkit: Bun integration<\/a> at aspire.dev.<\/li>\n<li><strong>\ud83d\udcac Give us feedback:<\/strong> We&#8217;d love to hear what you think \u2014 file issues or join discussions on the <a href=\"https:\/\/github.com\/microsoft\/aspire\">Aspire GitHub repo<\/a>.<\/li>\n<li><strong>\ud83c\udf10 Join the community:<\/strong> Follow us and connect with other Aspire developers at <a href=\"https:\/\/aspire.dev\/community\/\">aspire.dev\/community<\/a>.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Aspire 13.2 keeps the JavaScript story moving with Bun for Vite, more predictable containers, and small but meaningful fixes across debugging and builds.<\/p>\n","protected":false},"author":24662,"featured_media":386,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1,52],"tags":[26,9,60,11,12],"class_list":["post-385","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-aspire-category","category-releases","tag-apphost","tag-aspire","tag-hosting-integrations","tag-integrations","tag-javascript"],"acf":[],"blog_post_summary":"<p>Aspire 13.2 keeps the JavaScript story moving with Bun for Vite, more predictable containers, and small but meaningful fixes across debugging and builds.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/aspire\/wp-json\/wp\/v2\/posts\/385","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/aspire\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/aspire\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/aspire\/wp-json\/wp\/v2\/users\/24662"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/aspire\/wp-json\/wp\/v2\/comments?post=385"}],"version-history":[{"count":1,"href":"https:\/\/devblogs.microsoft.com\/aspire\/wp-json\/wp\/v2\/posts\/385\/revisions"}],"predecessor-version":[{"id":387,"href":"https:\/\/devblogs.microsoft.com\/aspire\/wp-json\/wp\/v2\/posts\/385\/revisions\/387"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/aspire\/wp-json\/wp\/v2\/media\/386"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/aspire\/wp-json\/wp\/v2\/media?parent=385"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/aspire\/wp-json\/wp\/v2\/categories?post=385"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/aspire\/wp-json\/wp\/v2\/tags?post=385"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}