Skip to content

[APPS] Use separate vite.build() for backend functions, drop Rollup backend support#292

Open
sdkennedy2 wants to merge 1 commit intomasterfrom
sdkennedy2/apps-vite-backend-build
Open

[APPS] Use separate vite.build() for backend functions, drop Rollup backend support#292
sdkennedy2 wants to merge 1 commit intomasterfrom
sdkennedy2/apps-vite-backend-build

Conversation

@sdkennedy2
Copy link
Collaborator

@sdkennedy2 sdkennedy2 commented Mar 20, 2026

Motivation

Backend functions were previously built by injecting virtual modules into the host bundler's build via resolveId/load hooks, with separate Rollup and Vite plugin implementations that duplicated logic. This approach was fragile — it coupled backend function bundling to the host build's configuration (plugins, aliases, output settings) and required maintaining two codepaths (Rollup + Vite).

This PR switches to a standalone vite.build() call that runs after the host build completes, giving full control over the backend build configuration. It also drops Rollup backend support entirely, simplifying to vite-only.

Changes

Replaced the "inject into host build" approach with a dedicated vite.build() for backend functions:

// In closeBundle hook (runs after host build finishes):
const result = await vite.build({
    configFile: false,       // Don't inherit user's vite plugins
    build: {
        write: true,
        outDir: tempDir,     // Isolated output directory
        rollupOptions: {
            input: virtualEntries,
            output: { format: 'es', entryFileNames: '[name].js' },
            treeshake: false,  // Preserve action-catalog bridges intact
        },
    },
    plugins: [/* virtual module resolver */],
});

Why a separate build? Backend functions need different build settings than the frontend — no minification, ES module format, preserved entry signatures, and no interference from the user's vite plugins. Running a standalone vite.build() with configFile: false provides this isolation cleanly.

Key changes:

  • Deleted backend/rollup.ts — Rollup backend support removed
  • Simplified backend/index.ts — removed resolveId/load hooks, now just delegates to the vite plugin
  • New buildBackendFunctions() in backend/vite/index.ts — runs a separate vite.build() via closeBundle hook, writes output to a temp directory, populates backendOutputs map for the upload plugin
  • Refactored virtual-entry.ts — extracted generateMainBody() helper for reuse
  • Updated shared.tsisActionCatalogInstalled() now accepts a fromDir parameter for correct resolution when the plugin is linked, fixed regex escaping in action-catalog bridge
  • Restricted backendSupportedBundlers from ['rollup', 'vite'] to ['vite']

QA Instructions

  1. Scaffold or use an existing high code app with backend functions
  2. Link the local vite plugin and run yarn dev in build-plugins
  3. Run a production build (npx vite build) and verify backend function .js files are generated and included in the upload archive
  4. Confirm the build works without the user's vite.config.ts plugins interfering with the backend build

Blast Radius

  • Only affects vite production builds when apps.backendDir is configured
  • Rollup users with backend functions will now see a warning that backend functions are not supported for their bundler (previously attempted but was untested)
  • No impact on webpack, esbuild, or rspack users

Documentation

…ackend support

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sdkennedy2 sdkennedy2 requested a review from yoannmoinet as a code owner March 20, 2026 20:38
Copy link
Collaborator Author

sdkennedy2 commented Mar 20, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant