Skip to content

[APPS] Support importing .backend.ts files as RPC proxies from frontend code#306

Draft
sdkennedy2 wants to merge 1 commit intosdkennedy2/apps-vite-dev-serverfrom
sdkennedy2/apps-backend-ts-imports
Draft

[APPS] Support importing .backend.ts files as RPC proxies from frontend code#306
sdkennedy2 wants to merge 1 commit intosdkennedy2/apps-vite-dev-serverfrom
sdkennedy2/apps-backend-ts-imports

Conversation

@sdkennedy2
Copy link
Copy Markdown
Collaborator

@sdkennedy2 sdkennedy2 commented Apr 2, 2026

Motivation

Currently, backend functions must live in a dedicated backend/ directory to be discovered and bundled. This means frontend code has no ergonomic way to import a backend function directly — developers have to know the function name as a string and wire up the executeBackendFunction call manually.

This PR adds support for co-locating backend functions alongside frontend code using a *.backend.ts naming convention. When frontend code imports a .backend.ts file, the build system automatically intercepts the import and serves a lightweight RPC proxy instead of the real server-side source.

Changes

Introduced a Vite plugin (backend-proxy-plugin.ts) that hooks into resolveId and load to intercept *.backend.ts imports in frontend code. When such an import is detected:

  1. The real file path is resolved to verify it exists
  2. The import is redirected to a virtual module (prefixed with \0dd-backend-proxy:)
  3. The virtual module serves a generated proxy that delegates to executeBackendFunction from @datadog/apps-function-query
// Frontend code — just import the backend function directly:
import { getGreeting } from './getGreeting.backend';

const result = await getGreeting('world');

The generated proxy module looks like:

import { executeBackendFunction } from '@datadog/apps-function-query';

export async function getGreeting(...args) {
    return executeBackendFunction('getGreeting', args);
}

Key architectural decisions:

  • Proxy codegen (proxy-codegen.ts): Separated into its own module for testability. Generates a thin wrapper that routes through the existing executeBackendFunction transport layer (dev-server HTTP or iframe postMessage).
  • Lazy discovery merging: Functions discovered via *.backend.ts imports are merged with directory-discovered functions at both closeBundle (production) and configureServer (dev) time. Deduplication is by function name.
  • Dev server getter pattern: createDevServerMiddleware now accepts a () => BackendFunction[] getter so that lazily-discovered functions are visible without restarting the dev server.
  • hasBackend moved to upload time: The hasBackend flag now checks backendOutputs.size instead of the initial discovery count, ensuring import-discovered functions are included in the backend/frontend asset split.

QA Instructions

  1. Create a *.backend.ts file outside the backend/ directory (e.g. src/getGreeting.backend.ts)
  2. Import it from a frontend component
  3. Verify the dev server serves the proxy module (check browser devtools — the import should resolve to the generated proxy, not the real file)
  4. Verify the function is callable through the dev server middleware
  5. Run a production build and confirm the backend function is bundled and uploaded

Blast Radius

  • Only affects the apps plugin's Vite integration (packages/plugins/apps/src/vite/)
  • No changes to other bundler integrations (esbuild, webpack, etc.)
  • The dev server middleware signature changed to accept a getter function, but this is an internal API
  • Gated to files matching the *.backend.(ts|tsx|js|jsx) pattern — no impact on regular imports

Documentation

Copy link
Copy Markdown
Collaborator Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@sdkennedy2 sdkennedy2 changed the title Support importing .backend.ts files as RPC proxies from frontend code [APPS] Support importing .backend.ts files as RPC proxies from frontend code Apr 2, 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