Skip to content

[APPS] Tree-shake backend function bundles - #538

Merged
gh-worker-dd-mergequeue-cf854d[bot] merged 3 commits into
masterfrom
kelly.sun/apps-backend-treeshake
Oct 2, 2026
Merged

gh-worker-dd-mergequeue-cf854d[bot] merged 3 commits into
masterfrom
kelly.sun/apps-backend-treeshake

Conversation

@ksun154

@ksun154 ksun154 commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

What and why?

This is an alternative to #533 for the pitchGPT HTTP 413 failure ("bundle exceeds the maximum decompressed size of 52 MB").

Each exported backend function is bundled by its own vite.build(), from a virtual entry that imports only that one export. The shared backend config set rollupOptions.treeshake: false, so
Rollup kept every module the .backend.ts file imports, including code that only sibling exports use. A file with N exports therefore shipped N copies of its whole import graph. That is the
"14× for the largest file" multiplier in #533. Minifying makes each copy smaller but keeps all of them; tree-shaking removes the duplication.

I found no stated reason for treeshake: false. It arrived with the switch to separate vite.build() calls in e154acf, with no comment or commit-message rationale.

This PR only enables tree-shaking. It does not minify; minify: false is unchanged.

How?

  • packages/plugins/apps/src/vite/build-config.ts: treeshake: false → treeshake: true. Production and dev-server builds share this config.
  • Standard tree-shaking keeps each module's top-level side effects. It drops a module's import-time code only when the package declares "sideEffects": false, which is the same behavior as the
    frontend build.
  • Static checks and connection-ID collection run in moduleParsed, which happens before tree-shaking. They still see every imported module, so allowlists and banned-import detection are
    unchanged.
  • The injected setBackend / setExecuteActionImplementation calls run inside main(), so they are reachable and kept.

Testing

  • New regression test in build-config.test.ts. It runs a real Vite build and checks that:
    • the used export and an imported module's import-time side effect are kept;
    • a helper used only by a sibling export, and an unused dependency export, are dropped.
  • The test fails on master (the sibling-only code is present in the bundle) and passes with this change.
  • packages/plugins/apps: 35 suites, 747 passed, 1 skipped. This includes the real @datadog/apps-backend SDK integration build and the local-execution suites.
  • ESLint and tsc --noEmit are clean.

Measurements

Both builds have minification off.

Total backend JS
Repo fixture (apps_backend_project, 7 functions), master 90,122 B
Repo fixture, this PR 71,271 B (−21%)
Synthetic file, 5 exports (zod / lodash-es / date-fns), master 8,920 KB
Synthetic file, this PR 284 KB (−97%)

The fixture has about one export per file, so it understates the gain for apps with many exports per file. pitchGPT has not been measured yet.

Risks and follow-ups

  • Risk: a dependency that wrongly declares "sideEffects": false but relies on import-time code would lose that code. The frontend build has the same exposure. Fallback: treeshake: { moduleSideEffects: true }, at the cost of keeping more unused code.
  • Minification is deferred, not rejected. It would still help, since the limit is on decompressed size, but it makes function-log stack traces hard to read (renamed locals, one long line, no server-side source maps known), lets production diverge from dev, and Proposal: smaller App Builder backend bundles #533's version adds a permanent apps.backend.minify option. A lighter variant (esbuild: { minifyIdentifiers: false }, untested) keeps local names readable.
  • Next: merge this, measure pitchGPT, and add minification and Proposal: smaller App Builder backend bundles #533's decompressed-size warning only if the size is still close to the limit.

Each exported backend function is bundled by its own vite.build(), and
treeshake: false made every bundle carry the full import graph of its
.backend.ts file, including code only sibling exports use. Enable
standard tree-shaking so each bundle contains only what its function
reaches.
@ksun154
ksun154 marked this pull request as ready for review October 1, 2026 17:28
@ksun154
ksun154 requested a review from a team as a code owner October 1, 2026 17:28
@ksun154
ksun154 requested review from tyffical and removed request for a team October 1, 2026 17:28
@datadog-datadog-prod-us1

datadog-datadog-prod-us1 Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Tests

✅ All CI checks and tests passed.

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: a243726 | Docs | View more details | Give us feedback!

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The new test violates the repository’s no-inlined-function-call-arguments standard.

Review effort: Balanced
Findings: 1 Low severity

Open (1)
What changed in this PR

Enables backend bundle tree-shaking to reduce duplicated code across separately bundled exports.

Changes:

  • Enables Rollup tree-shaking for backend builds.
  • Adds regression coverage for unused exports and import-time side effects.
File Description
packages/​plugins/​apps/​src/​vite/​build-config.ts Enables and documents tree-shaking.
packages/​plugins/​apps/​src/​vite/​build-config.test.ts Tests retained side effects and removed unused code.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/plugins/apps/src/vite/build-config.test.ts
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

The focused configuration change is supported by realistic regression coverage with no unresolved correctness issues.

Review effort: Balanced
Findings: None

Resolved since last review (1)

…end-treeshake

# Conflicts:
#	packages/plugins/apps/src/vite/build-config.test.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants