Skip to content

[RUM-18428] Change copyRuntimeDependencies default value - #216

Open
cdn34dd wants to merge 2 commits into
mainfrom
carlosnogueira/RUM-18428/change-runtime-dependency-option
Open

cdn34dd wants to merge 2 commits into
mainfrom
carlosnogueira/RUM-18428/change-runtime-dependency-option

Conversation

@cdn34dd

@cdn34dd cdn34dd commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

Motivation

Currently, Electron Forge’s Vite and Webpack plugins configure Electron Packager to include only the contents of .vite or .webpack in the packaged application.

This leads to issues with externalized dependencies such as @datadog/electron-sdk and dd-trace, since these dependencies cannot currently be safely bundled and must remain available at runtime.

To address this limitation, we previously handled dependency copying inside the Datadog bundler plugins. This minimized the actions required from users and simplified SDK setup.

The issue is that dependency management is complex, with several package managers and installation layouts, including npm, Yarn, Yarn Plug’n’Play, and pnpm. Supporting all these layouts reliably has proven difficult and is beyond the intended scope of these bundler plugins.

As such, the goal of this PR is to change the default value of the copyRuntimeDependencies option in the Vite, Webpack, and esbuild plugins from true, where the SDK handles dependency copying, to false, where dependency staging becomes the responsibility of the chosen application packager.

copyRuntimeDependencies: true remains available as a best-effort compatibility fallback for setups where the packager cannot stage external dependencies.

A couple of things should be considered. Out-of-the-box production dependency staging is supported by electron-builder and by plain Electron Forge. Forge’s core packaging flow, provided by @electron-forge/core, delegates application assembly and production dependency pruning to @electron/packager. These are parts of the same Forge packaging flow rather than separate packaging configurations.

However, Forge’s @electron-forge/plugin-vite and @electron-forge/plugin-webpack integrations normally restrict the packaged application contents to .vite and .webpack, respectively. Webpack can relocate modules it processes, but the SDK and dd-trace are deliberately externalized and excluded from that relocation.

For these scenarios, users must make a small change to packagerConfig.ignore in their forge.config so that Forge also stages production dependencies from the application’s root node_modules. The required configuration is documented in README.md.

The Forge Vite and Webpack integration fixtures use this configuration with copyRuntimeDependencies omitted. Their packaged instrumentation tests verify startup instrumentation, renderer error propagation, main-process resource events and trace spans, custom-session preload injection, and crash reporting. The packaged ASAR archives were also verified to contain both @datadog/electron-sdk and dd-trace.

This approach also has a downside. Electron Packager prunes development dependencies, but it cannot determine which production dependencies have already been included in the Vite or Webpack bundles. Consequently, the packaged application may retain production dependencies that were already bundled, potentially increasing its overall size.

Applications can reduce this duplication by keeping only genuine runtime dependencies in dependencies and moving packages that are fully bundled into devDependencies. copyRuntimeDependencies: true also remains available as a best-effort alternative, although it is known to behave differently across package-manager installation layouts.

Electron Forge is working on improved handling of native external dependencies in the Vite plugin through electron/forge#4232. However, that PR is currently a draft, is Vite-specific, and focuses on native Node modules. It does not address the Webpack plugin or fully remove the need for this workaround for the SDK and dd-trace. Until equivalent support is merged and released, we need to support the approach described above.

Changes

Test instructions

Checklist

  • Tested locally (playground)
  • Added unit tests for this change.
  • Added e2e/integration tests for this change.
  • Updated related documentation.
  • Agentic code review findings addressed or explicitly dismissed.

@cdn34dd

cdn34dd commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 8, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-14T15:34:50.941804Z f96d7f1 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale comment

PR Review — Score: 4.7 / 5

This is a well-motivated, intentional breaking change that shifts runtime dependency staging from bundler plugins to application packagers. The implementation is consistent across all three plugins (!== true guard), unit tests and integration fixtures are inverted correctly, Forge apps include the required packagerConfig.ignore override, and the new docs/RUNTIME_DEPENDENCIES.md plus README/ARCHITECTURE updates give customers a clear migration path. I would approve once the minor documentation gaps below are addressed (or explicitly deferred to the release PR).

Why 4.7: Clear rationale, thorough cross-plugin consistency, strong integration coverage (including ASAR assertions and renamed plugin-copy variant), and a dedicated Forge setup guide. The PR body explains trade-offs (bundle duplication, package-manager layouts) honestly.

Why not 5: A breaking default change should land with a CHANGELOG entry before release, and the README now omits standalone Vite/Webpack plugin snippets that non-Forge users (electron-vite, manual Vite + electron-builder) previously had inline.


Findings

  • [Minor] Missing CHANGELOG entry — The @default false flip is a breaking change for Forge Vite/Webpack users who relied on implicit plugin copying; add a 💥 Breaking Changes note before the next release.
  • [Minor] README plugin examples narrowed — Standalone Vite/Webpack setup snippets were removed; only Forge packagerConfig and an esbuild example remain under “Other packagers.”

Architectural flow

sequenceDiagram
    participant Dev as Developer
    participant Plugin as Bundler plugin
    participant Packager as Electron packager
    participant App as Packaged app

    Note over Plugin,Packager: Previous default copyRuntimeDependencies true
    Dev->>Plugin: datadogVitePlugin()
    Plugin->>Plugin: externalize SDK and dd-trace
    Plugin->>Plugin: copyPackageTree into dist node_modules
    Packager->>App: package bundler output only

    Note over Plugin,Packager: New default copyRuntimeDependencies false
    Dev->>Plugin: datadogVitePlugin()
    Plugin->>Plugin: externalize SDK and dd-trace only
    Dev->>Packager: packagerConfig.ignore retains node_modules
    Packager->>App: prune and stage production dependency tree
Loading

Before: Bundler plugins owned dependency staging by default, copying @datadog/electron-sdk and dd-trace into the build output’s node_modules. This worked across package-manager layouts but was fragile (pnpm/Yarn PnP) and outside the plugins’ intended scope.

After: Packager-owned staging is the default. Forge Vite/Webpack apps override packagerConfig.ignore to retain root node_modules alongside .vite/.webpack, letting Electron Packager prune and include the production tree. copyRuntimeDependencies: true remains as a best-effort fallback.

Open in Web View Automation 

Sent by Cursor Automation: electron-sdk reviews

Comment thread README.md
Comment thread docs/RUNTIME_DEPENDENCIES.md

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ae753b1a66

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread README.md Outdated
Comment thread docs/ARCHITECTURE.md Outdated
@cdn34dd
cdn34dd force-pushed the carlosnogueira/RUM-18428/change-runtime-dependency-option branch from ae753b1 to e6ef345 Compare September 11, 2026 10:51
@cdn34dd

cdn34dd commented Sep 14, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@datadog-datadog-prod-us1

datadog-datadog-prod-us1 Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

Pipelines

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

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale comment

PR Review — Score: 4.8 / 5

Follow-up commits address the documentation gaps from the earlier review: the README again includes Vite and Webpack plugin wiring under “Other packagers,” docs/RUNTIME_DEPENDENCIES.md cross-links those examples, and docs/ARCHITECTURE.md scopes optional-dependency behavior to plugin-owned staging. The default flip is implemented consistently (copyRuntimeDependencies !== true across Vite, Webpack, and esbuild), unit tests and integration fixtures are inverted sensibly (plugin-copy vs packager-owned default), and Forge fixtures include the required packagerConfig.ignore override. I would approve; add a CHANGELOG breaking note before the release (or in the release PR if that is your process). GitLab dd-gitlab/e2e was still pending when this review was posted.

Why 4.8: Clear motivation, thorough customer-facing migration docs, cross-plugin consistency, and strong integration coverage (including the renamed plugin-copy electron-builder variant and Forge ASAR assertions described in the PR body).

Why not 5: copyRuntimeDependencies defaulting to false is a breaking behavioral change for anyone who relied on implicit plugin copying (especially Forge Vite/Webpack without packagerConfig.ignore); CHANGELOG.md does not yet document it on this branch.


Findings

  • [Minor] Missing CHANGELOG entry — Document the @default false flip under Breaking Changes before the next release so upgraders know to configure packagers or opt into copyRuntimeDependencies: true.
  • [Nit] Docs index scope — docs/README.md describes RUNTIME_DEPENDENCIES.md as Forge-only, but the guide also covers other packagers.

Architectural flow

sequenceDiagram
    participant Dev as Developer
    participant Plugin as Bundler plugin
    participant Packager as Electron packager
    participant App as Packaged app

    Note over Plugin,Packager: Previous default copyRuntimeDependencies true
    Dev->>Plugin: datadogVitePlugin()
    Plugin->>Plugin: externalize SDK and dd-trace
    Plugin->>Plugin: copyPackageTree into dist node_modules
    Packager->>App: package bundler output only

    Note over Plugin,Packager: New default copyRuntimeDependencies false
    Dev->>Plugin: datadogVitePlugin()
    Plugin->>Plugin: externalize SDK and dd-trace only
    Dev->>Packager: packagerConfig.ignore retains node_modules
    Packager->>App: prune and stage production dependency tree
Loading

Before: Bundler plugins owned runtime dependency staging by default, copying @datadog/electron-sdk and dd-trace into the build output’s node_modules—fragile across package-manager layouts and outside the plugins’ intended scope.

After: Packager-owned staging is the default. Forge Vite/Webpack apps override packagerConfig.ignore to retain root node_modules alongside .vite/.webpack. copyRuntimeDependencies: true remains a best-effort compatibility fallback.

Open in Web View Automation 

Sent by Cursor Automation: electron-sdk reviews

Comment thread docs/README.md Outdated
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: 5664c56481

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@cdn34dd
cdn34dd force-pushed the carlosnogueira/RUM-18428/change-runtime-dependency-option branch from 5664c56 to f96d7f1 Compare September 14, 2026 15:03
@cdn34dd
cdn34dd marked this pull request as ready for review September 14, 2026 15:31
@cdn34dd
cdn34dd requested a review from a team as a code owner September 14, 2026 15:31
@cdn34dd
cdn34dd requested a review from bcaudan September 14, 2026 15:31

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

PR Review — Score: 4.9 / 5

This PR cleanly shifts the default runtime-dependency staging path from bundler plugins to application packagers. The copyRuntimeDependencies !== true guard is applied consistently across Vite, Webpack, and esbuild; unit tests and the inverted plugin-copy integration fixture match the new semantics; Forge fixtures include the required packagerConfig.ignore override; and customer docs (README, docs/RUNTIME_DEPENDENCIES.md, docs/ARCHITECTURE.md, docs index) explain migration and trade-offs. Follow-up commits since the last automation pass restored non-Forge Vite/Webpack examples and broadened the docs index blurb. I would approve; add a CHANGELOG breaking note before release (here or in the release PR if that is your process).

Why 4.9: Intentional, well-documented breaking default with strong cross-plugin consistency and integration coverage (packaged instrumentation paths and ASAR layout assertions described in the PR body).

Why not 5: CHANGELOG.md on this branch still does not record the @default false flip under Breaking Changes, which upgraders need when moving off implicit plugin copying.


Findings

  • [Minor] Missing CHANGELOG entry — Document the copyRuntimeDependencies default change under Breaking Changes before the next release so Forge Vite/Webpack users know to adjust packagerConfig.ignore or opt into copyRuntimeDependencies: true.

Architectural flow

sequenceDiagram
    participant Dev as Developer
    participant Plugin as Bundler plugin
    participant Packager as Electron packager
    participant App as Packaged app

    Note over Plugin,Packager: Previous default copyRuntimeDependencies true
    Dev->>Plugin: datadogVitePlugin()
    Plugin->>Plugin: externalize SDK and dd-trace
    Plugin->>Plugin: copyPackageTree into dist node_modules
    Packager->>App: package bundler output only

    Note over Plugin,Packager: New default copyRuntimeDependencies false
    Dev->>Plugin: datadogVitePlugin()
    Plugin->>Plugin: externalize SDK and dd-trace only
    Dev->>Packager: packagerConfig.ignore retains node_modules
    Packager->>App: prune and stage production dependency tree
Loading

Before: Bundler plugins owned runtime dependency staging by default, copying @datadog/electron-sdk and dd-trace into the build output’s node_modules—fragile across package-manager layouts and outside the plugins’ intended scope.

After: Packager-owned staging is the default. Forge Vite/Webpack apps override packagerConfig.ignore to retain root node_modules alongside .vite/.webpack. copyRuntimeDependencies: true remains a best-effort compatibility fallback.

Open in Web View Automation 

Sent by Cursor Automation: electron-sdk reviews

* compatibility fallback only when the packager cannot do so.
*
* @default true
* @default false

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Minor] Release note — This @default false change is breaking for anyone who relied on implicit plugin copying (especially Forge Vite/Webpack without packagerConfig.ignore). Please add a 💥 Breaking Changes entry to CHANGELOG.md before the next release, or confirm it will land in the release PR.

Comment on lines +14 to +15
* 3. Optionally copies dd-trace and @datadog/electron-sdk into the build
* output's node_modules when the application packager does not stage them.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

💬 suggestion: ‏could it be interesting to mention that it is achieved with copyRuntimeDependencies: true? since the option is not in the plugin jsdoc anymore

same with webpack plugin but not with esbuild plugin.
Should we not have the same doc structure in esbuild plugin?

Comment thread README.md
**Vite** (including Electron Forge with Vite and electron-vite):
##### Electron Forge

Keep `copyRuntimeDependencies` disabled. Configure Forge to package root `node_modules` alongside its

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

💬 suggestion: Keep copyRuntimeDependencies disabled. is the first mention of copyRuntimeDependencies in this doc. Maybe adding a paragraph in bundler plugins section could help understanding the purpose of this option before mentioning it.‏

Comment on lines +26 to +36
it('is delegated to the packager by default for webpack', () => {
let defaultAfterEmitCalls = 0;
new DatadogWebpackPlugin().apply(
createWebpackCompiler(() => {
defaultAfterEmitCalls += 1;
})
);
expect(defaultAfterEmitCalls).toBe(1);
expect(defaultAfterEmitCalls).toBe(0);

let managedAfterEmitCalls = 0;
new DatadogWebpackPlugin({ copyRuntimeDependencies: false }).apply(
let pluginCopyAfterEmitCalls = 0;
new DatadogWebpackPlugin({ copyRuntimeDependencies: true }).apply(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Here it is not delegated to the packager though, no?

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.

2 participants