From b8f9124e0909391a7cefb30c1770eaa076785f75 Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Fri, 25 Sep 2026 18:30:44 +0000 Subject: [PATCH 1/2] Add RFC: WarpDrive: Dropping V1 Addon and Classic ember-cli Macros Support in 6.0 --- ...classic-ember-cli-macros-support-in-6-0.md | 352 ++++++++++++++++++ 1 file changed, 352 insertions(+) create mode 100644 text/0000-dropping-v1-addon-and-classic-ember-cli-macros-support-in-6-0.md diff --git a/text/0000-dropping-v1-addon-and-classic-ember-cli-macros-support-in-6-0.md b/text/0000-dropping-v1-addon-and-classic-ember-cli-macros-support-in-6-0.md new file mode 100644 index 0000000000..61cb49c0ec --- /dev/null +++ b/text/0000-dropping-v1-addon-and-classic-ember-cli-macros-support-in-6-0.md @@ -0,0 +1,352 @@ +--- +stage: proposed +start-date: 2026-09-25T00:00:00.000Z +release-date: +release-versions: +teams: + - data + - cli +prs: + accepted: +project-link: +suite: +--- + +# WarpDrive: Dropping V1 Addon and Classic ember-cli Macros Support in 6.0 + +## Summary + +WarpDrive's 6.0 major drops two pieces of classic Ember infrastructure: the V1 addon shim +every `@warp-drive/*`/`@ember-data/*`/`ember-data` package still carries as a compatibility +fallback (`addonV1Shim` from `@embroider/addon-shim`, and the `___legacy_support` branch in +`setConfig` that exists only to receive `app.options.emberData`), and the classic ember-cli +macros configuration surface (`setConfig(app, __dirname, config)` called from +`ember-cli-build.js`, `buildMacros()` + `setConfig(macrosConfig, config)` wired by hand into +`babel.config.mjs`, and the accompanying `babel-plugin-debug-macros` entry). After 6.0, every +consumer configures WarpDrive exclusively through the bundler plugin introduced in +[RFC 0002](/rfcs/0002-warp-drive-build-plugin), and every WarpDrive package ships as a +V2-only addon with no V1 fallback. A non-embroider classic Ember build — one without +`@embroider/compat`'s `compatBuild` in `ember-cli-build.js` — can no longer resolve WarpDrive +as an ember-cli addon; it can still depend on WarpDrive as a plain npm package via +`ember-auto-import`, with the tradeoffs that entails (see "Ecosystem implications"). + +## Motivation + +RFC 0002 introduced the build plugin and deprecated the babel-based configuration path, but +it deliberately kept two escape hatches alive through the 6.0 boundary to de-risk that +proposal on its own: classic ember-cli apps could keep calling +`setConfig(app, __dirname, config)` unchanged, with an automatic babel bridge the addon +wires up for them, and WarpDrive's own packages kept their `addonV1Shim` fallback so that an +app running a fully classic (non-embroider) build could still resolve them. Both of those +compatibility paths carry real, ongoing cost, and neither is doing what it was built for +anymore: + +**1. The V1 shim keeps a resolution path alive that WarpDrive's own tooling already assumes is +absent.** Apps that haven't adopted embroider at all are still a real, supported part of the +Ember ecosystem — this RFC does not claim otherwise, and does not remove WarpDrive's +consumability by them outright. What the shim specifically buys such an app is resolving +WarpDrive **as an ember-cli addon** — package discovery, `app-js`/`public-assets` merging, +the `included` hook — without embroider's V2 addon support to interpret those conventions. A +classic app could, before and after this RFC, still bring WarpDrive in some other way (for +example via `ember-auto-import` treating it as an external npm dependency — see "Ecosystem +implications" below for what that path does and doesn't get you). What goes away at 6.0 is +only the addon-resolution path, not consumability in general. That's still worth removing: +WarpDrive's +own minimum-supported Ember versions already require embroider for anything but the most +trivial app (Vite, TypeScript, and strict-mode templates all assume it), so the shim spends +real weight — `@embroider/addon-shim` as a dependency of every published package, plus the +`ember-addon.version === 1` branch in every `addon-main.cjs` deleting `treeForApp` — keeping +the *addon-resolution* path alive for a build shape the rest of WarpDrive's tooling already +assumes is absent. + +**2. The classic macros path is the thing RFC 0002 was written to replace.** Its own +motivation section lists the failure modes directly: a babel pipeline is a hard requirement +in ecosystems that don't have one, the wiring is easy to get wrong (`buildMacros`, +`setConfig`, `...macros()`, `...Macros.babelMacros`, and a `babel-plugin-debug-macros` entry, +each a chance to omit a piece), and multiple copies of `@embroider/macros` in a dependency +tree silently fail to coordinate. Every one of those problems still exists as long as the +classic path is reachable at all — a deprecation warning does not remove a footgun, it just +labels it. The `___legacy_support` branch in `setConfig` (`warp-drive-packages/build-config/src/index.ts`) +exists solely to reconcile `app.options.emberData` (read by the V1 shim's `included` hook) +against an app that also calls `setConfig` directly — a reconciliation step whose only job is +supporting the path this RFC removes. + +**3. Two supported configuration paths is a permanent maintenance and documentation tax.** +`guides/configuration/index.md` currently carries three tabs — Simple Config, Advanced +Config, Ember Apps (classic) — for what is conceptually one operation: hand WarpDrive its +config object. Every new `WarpDriveConfig` option, every bug in config resolution, and every +support question has to account for three wiring shapes instead of one. RFC 0002 already +unified Simple/Advanced Config into the plugin; this RFC finishes the job by retiring the +third. + +The expected outcome: one configuration surface (the build plugin, with `compatWith` and +friends), one addon format (V2), `@embroider/macros` and `@embroider/addon-shim` off every +WarpDrive package's dependency list, and a support matrix that no longer has to reason about +classic (non-embroider) Ember builds at all. + +## Detailed design + +### What "V1 addon support" means here, precisely + +Every `@warp-drive/*`, `@ember-data/*`, and `ember-data` package ships `addon-main.cjs` +built on: + +```js +'use strict'; +const { addonShim } = require('@warp-drive/core/addon-shim.cjs'); // re-exports addonV1Shim +const addon = addonShim(__dirname); +const pkg = require('./package.json'); +if (pkg['ember-addon'].version === 1) { + delete addon.treeForApp; +} +``` + +`addonV1Shim` (from `@embroider/addon-shim`) is what lets a package written to the V2 addon +spec — no `index.js` addon class, no broccoli trees, just `app-js`/`public-assets` in +`package.json` — still resolve correctly for an ember-cli consumer that predates embroider's +V2 addon support. Every WarpDrive package already declares `"ember-addon": { "version": 2, +... }`; the `version === 1` branch is dead in practice today because nothing in the published +packages sets `version: 1`, but the shim itself, and the `included` hook it wraps (used to +funnel `app.options.emberData` into `setConfig` — see next section), stay live and load on +every classic-build consumer regardless. + +At 6.0: + +- `addon-main.cjs` is replaced by a plain V2 addon manifest with no shim, no `included` + hook, and no runtime branch on `ember-addon.version`. +- `@embroider/addon-shim` is removed from every WarpDrive package's dependencies. +- Resolving a WarpDrive package **as an ember-cli addon** requires an embroider-compatible + resolution (V2 addon support), whether that's a Vite build via `@embroider/vite`, or + `compatBuild` from `@embroider/compat` in a still-broccoli-based `ember-cli-build.js`. A + fully classic build — no embroider anywhere in the pipeline — cannot resolve WarpDrive + packages *as addons* at 6.0, the same way it already cannot resolve any other V2-only addon + in the ecosystem today. +- This is narrower than "cannot use WarpDrive at all" — see "Ecosystem implications" below for + the `ember-auto-import` fallback a fully classic app still has, and what it costs. + +### What "classic ember-cli macros config" means here, precisely + +Three call shapes, all accepted by `setConfig` today +(`warp-drive-packages/build-config/src/index.ts`), are removed: + +1. **The 3-argument classic form**, called from `ember-cli-build.js`: + + ```js + setConfig(app, __dirname, { compatWith: '4.12', deprecations: { /* ... */ } }); + ``` + + This is `isEmberClassicUsage` in `setConfig`'s implementation — it calls + `_MacrosConfig.for(context, appRoot)` to look up (or create) the app's embroider macros + config by side effect, rather than receiving one directly. + +2. **The `emberData` key on an app's own options object**, passed straight to the `EmberApp` + constructor with no `setConfig` import at all: + + ```js + // ember-cli-build.js + const app = new EmberApp(defaults, { + emberData: { compatWith: '4.12', deprecations: { /* ... */ } }, + }); + ``` + + This is the oldest of the three shapes and, unlike the other two, isn't reached by + calling `setConfig` yourself — it's read by the V1 shim's `included` hook (see previous + section), which calls `setConfig(app, dirname, { ...app.options?.emberData, + ___legacy_support: true })` on every app regardless of whether that app configured + WarpDrive any other way. `setConfig`'s implementation already throws if this key and a + direct `setConfig` call are both present, and carries a console-warning message for this + exact key — written but deliberately never enabled (`warp-drive-packages/build-config/src/index.ts`, + commented out pending a package rearrangement) — that this RFC's immediate deprecation + (see "Deprecating now, removing in 6.0") supersedes and finally ships, as a proper + `expectDeprecation()`-testable deprecation rather than a plain `console.warn`. + +3. **The 2-argument advanced form** aimed at a hand-rolled `buildMacros()` instance: + + ```js + const Macros = buildMacros({ configure: (config) => setConfig(config, { compatWith: '5.7' }) }); + ``` + + paired with a manually-added `babel-plugin-debug-macros` entry to convert + `deprecate`/`warn` calls, and `...Macros.babelMacros` in the babel plugin list. + +At 6.0, `setConfig` keeps exactly one signature: + +```ts +export function setConfig(config: WarpDriveConfig): void; +``` + +which registers the config directly on the build plugin's registry (the mechanism RFC 0002 +describes under "One config, no matter how many copies") — no `MacrosConfig`, no +`buildMacros`, no app/context object, no `appRoot` string. `setConfig` becomes a thin wrapper +that plugin users don't even need to call directly; passing the same options object to +`warpDrive.vite(options)` (or the adapter for whichever bundler) does the same thing. + +Calling `setConfig` with 2 or 3 arguments, or calling `buildMacros`/`babelPlugin` from +`@warp-drive/core/build-config`, throws synchronously at build configuration time (not a +runtime deprecation warning — by 6.0 these entry points no longer exist in the published +type signatures or the compiled output) with a message pointing at the migration guide: + +``` +Error: setConfig() no longer accepts an ember-cli `app` object or `appRoot` string as of +WarpDrive 6.0. Configure WarpDrive through the build plugin instead: + + // vite.config.mjs + import { warpDrive } from '@warp-drive/core/build-plugin'; + plugins: [...ember(), warpDrive.vite({ compatWith: '5.7' })] + +Migration guide: https://docs.warp-drive.io/guides/build-plugin-migration +``` + +`babelPlugin()`, the `macros()` helper, and the documented `babel-plugin-debug-macros` entry +are removed from `@warp-drive/core/build-config`'s exports entirely; importing them is a +module-resolution error, not a runtime warning. + +### Deprecating now, removing in 6.0 + +RFC 0002 proposed a staged rollout: the plugin ships silently alongside the classic path, +then a build notice one minor later, then a formal deprecation only in the last 5.x minor +before 6.0 — with removal itself deferred to 7.0, behind an automatically-injected babel +bridge gated by a flag for the full 6.0 beta cycle. + +This RFC collapses that timeline instead of extending it: both deprecations below ship in the +very next 5.x minor, alongside the plugin itself, rather than waiting for an interim build +notice — and both are removed outright at 6.0, with no bridge and no flag in either major. + +1. **Next 5.x minor:** the plugin ships, and both deprecations below fire immediately. + - `warp-drive.legacy-babel-config` — fires on every hit of `setConfig`'s + `isEmberClassicUsage` (3-arg) branch (covering both the direct + `setConfig(app, __dirname, config)` call and the `app.options.emberData` key, which + reaches the same branch through the V1 shim's `included` hook), and on every use of + `buildMacros()` + `setConfig(macrosConfig, config)`. This is orthogonal to which addon + resolution the app uses — an embroider app that still configures WarpDrive this way + gets this deprecation, not the next one. Supersedes RFC 0002's plan of a silent notice + followed by a formal deprecation two minors later; the notice and the deprecation + collapse into one, and this RFC also finally ships the `emberData`-key warning that + already exists in source but has stayed commented out (see "classic ember-cli macros + config" above). + - `warp-drive.v1-addon-support` — fires when WarpDrive is resolved without embroider's V2 + addon support at all, independent of which of the three config shapes the app uses. + Pinning down that detection precisely is open — see "Unresolved questions." + + Both are ordinary WarpDrive deprecations, not build notices: listed alongside the other + entries in `@warp-drive/build-config/deprecations`, testable with + `assert.expectDeprecation()`, and silenceable via the same `deprecations: { ... }` config + option as any other — silencing the warning does not change the removal date. +2. **6.0:** both are removed, per the "Detailed design" section above. There is no bridge and + no flag; an app that has not migrated by 6.0's release fails at build configuration time + with the error message shown above, and (if it is on a fully classic, non-embroider build) + can no longer resolve WarpDrive's packages as addons (see "Ecosystem implications" for its + remaining `ember-auto-import` fallback). + +Starting the warning immediately, rather than in the final 5.x minor as RFC 0002 planned, +gives every app the entire remaining 5.x release cycle to migrate instead of just its last +minor — even though the removal target (6.0, not 7.0) is sooner than RFC 0002's original +schedule. + +### Ecosystem implications + +- **A fully classic (non-embroider) app is not left with zero options**, only without addon + resolution. It can still adopt `ember-auto-import` and depend on WarpDrive as a plain npm + package, the same way it would depend on any non-Ember JS library. That path gets + WarpDrive's compiled output as an opaque external module: none of the build plugin's + transforms run over it, so there is no deprecation stripping, no canary feature toggling, + and no app-side flag imports — the app gets an unoptimized, always-development-shaped + build (or has to fall back to a CDN/unpkg copy). It is a real fallback, not a supported, + equivalent replacement for addon resolution. +- **Addons that depend on WarpDrive** and use the classic `setConfig(app, __dirname, ...)` + form in their own `index.js` `included` hook (a pattern several community addons copied + from WarpDrive's own guides before the plugin existed) break at 6.0 the same way an app + would, and need the same migration. +- **Ember Engines:** unaffected beyond the general migration — engines already resolve V2 + addons through the host app's embroider pipeline. +- **Blueprints:** the app blueprint's WarpDrive wiring, already updated to the plugin recipe + under RFC 0002, drops the classic `ember-cli-build.js` tab entirely rather than marking it + deprecated. +- **Lint rules:** none required; there is no runtime API surface change, only a build-time + configuration one. +- **`@embroider/macros` and `@embroider/addon-shim`** both leave every WarpDrive package's + `dependencies`, completing the removal RFC 0002 scheduled for WarpDrive's published output + format. + +## How we teach this + +The setup guide (`guides/configuration/index.md`) drops the "Ember Apps" (classic) tab +introduced under RFC 0002's interim period, leaving a single build-plugin recipe per bundler +— there is no longer a paradigm switch to teach at all, only "add this plugin to your +bundler config." The legacy package setup guide +(`guides/configuration/legacy-package-setup/`) is retitled to make clear it documents the 5.x +migration path, not a currently-supported configuration. + +The upgrade guide for 6.0 (`upgrading/v6/index.md`) gets a dedicated section listing, in +order: (1) confirm the app builds through embroider (Vite or `compatBuild`) rather than a +fully classic pipeline — a prerequisite independent of WarpDrive; (2) replace any +`setConfig(app, __dirname, ...)` / `buildMacros()` wiring with the plugin call shown above; +(3) delete the now-unused `@embroider/macros`, `babel-plugin-debug-macros`, and +`babel.config.mjs` entries that existed only for WarpDrive. Because both deprecation IDs +(`warp-drive.legacy-babel-config` and `warp-drive.v1-addon-support`) fire starting in the +very next 5.x minor rather than only in the last one before 6.0, most apps should reach 6.0 +having already completed this migration, with the entire remaining 5.x cycle to do it in, +rather than discovering it as a breaking change. + +## Drawbacks + +- **Shorter overall support window than RFC 0002 originally proposed.** RFC 0002 kept the + classic path and the V1 shim fully supported through 6.0 and promised an indefinite babel + bridge after that. This RFC removes both at 6.0 with no bridge at all — real apps that would + have had until 7.0 now have only until 6.0. The immediate deprecation partly offsets this: + the warning starts the moment this RFC lands rather than in 6.0's final beta, so affected + apps get the whole current major's release cycle to react, not just its last minor — but the + net window is still shorter than RFC 0002 promised. +- **Immediate, ecosystem-wide deprecation noise.** Every app still on the classic path or + relying on V1 addon resolution starts seeing both warnings on its very next upgrade, rather + than easing in via a silent-then-notice-then-deprecation ramp. This is deliberate — see + Motivation — but it is a real, immediate cost for apps that have not yet started migrating. +- **No escape hatch after 6.0.** Unlike the 7.0 "babel bridge remains available indefinitely" + promise in RFC 0002, this RFC leaves no supported way to configure WarpDrive without the + bundler plugin, and no supported way to resolve WarpDrive packages without embroider's V2 + addon support, once 6.0 ships. +- **Community addons that copied the classic recipe** from WarpDrive's own older guides (the + "Advanced Config" tab) inherit this break even if they never touch WarpDrive's plugin + themselves, since their own `included` hooks call the same removed `setConfig` shape. + +## Alternatives + +- **Keep RFC 0002's original schedule** (deprecate at 6.0, remove at 7.0 with an indefinite + babel bridge). Rejected here because it keeps every problem in the Motivation section + reachable for one more full major, and keeps `@embroider/macros` and `@embroider/addon-shim` + in WarpDrive's dependency tree that much longer. +- **Keep RFC 0002's staged ramp (silent → build notice → formal deprecation) but still remove + at 6.0 instead of 7.0.** Considered as a middle ground. Rejected: the ramp's only purpose is + easing apps into a warning that will eventually fire regardless, and shortening the removal + target to 6.0 without also starting the warning immediately would leave apps with less + total notice than today's plan, not more — the ramp made sense paired with a 7.0 removal, + not a 6.0 one. +- **Drop only the classic macros config, keep the V1 shim.** Rejected: the V1 shim's + `included` hook is what feeds `app.options.emberData` into the classic `setConfig` path in + the first place, so removing one without the other leaves a live entry point into code this + RFC deletes. +- **Drop only the V1 shim, keep classic macros config for embroider-based classic builds.** + Considered, since `compatBuild` apps without Vite could theoretically keep calling + `setConfig(app, __dirname, ...)` while still resolving WarpDrive as a V2 addon. Rejected for + consistency: RFC 0002's plugin already supports `compatBuild` pipelines (it runs ahead of + babel regardless of bundler), so there is no build shape left that needs the classic + signature once the plugin exists — keeping it only prolongs the two-paths maintenance cost + this RFC exists to end. +- **Ship the flag-gated automatic babel bridge from RFC 0002's unresolved question, then + remove it later.** Rejected: building and testing an automatic bridge (detecting the app's + babel setup and injecting compatible config) is nontrivial work for a path this RFC + proposes to delete outright; the effort is better spent on migration tooling (a codemod, see + Unresolved questions) that gets apps off the classic path rather than papering over it. + +## Unresolved questions + +- Whether a codemod should ship alongside the 6.0 release (or earlier, during the deprecation + period) that rewrites a classic `ember-cli-build.js` `setConfig` call and a `babel.config.mjs` + `buildMacros`/`setConfig` pair into the equivalent plugin call automatically, versus leaving + this as a documented manual migration. +- Whether the `warp-drive.v1-addon-support` deprecation can be made precise enough to fire + only for apps that would actually fail at 6.0 (i.e. those without embroider V2 addon + resolution), as opposed to firing for every app that hasn't explicitly opted into the + plugin yet, which would over-warn compatBuild-based apps that face no V1-addon break at all. +- How long the legacy package setup guide should stay published as a historical reference + for teams mid-upgrade, versus being removed once 6.0 is released. From 9e74cb6229604a46b6f63fd31c42b487ace85010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=A4=96=20WarpDrive=20RFC=20Sync?= <332362369+warpdrive-bot@users.noreply.github.com> Date: Fri, 25 Sep 2026 18:30:50 +0000 Subject: [PATCH 2/2] RFC #1239: fill prs.accepted and rename file with PR number --- ...g-v1-addon-and-classic-ember-cli-macros-support-in-6-0.md} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename text/{0000-dropping-v1-addon-and-classic-ember-cli-macros-support-in-6-0.md => 1239-dropping-v1-addon-and-classic-ember-cli-macros-support-in-6-0.md} (99%) diff --git a/text/0000-dropping-v1-addon-and-classic-ember-cli-macros-support-in-6-0.md b/text/1239-dropping-v1-addon-and-classic-ember-cli-macros-support-in-6-0.md similarity index 99% rename from text/0000-dropping-v1-addon-and-classic-ember-cli-macros-support-in-6-0.md rename to text/1239-dropping-v1-addon-and-classic-ember-cli-macros-support-in-6-0.md index 61cb49c0ec..00cedebb24 100644 --- a/text/0000-dropping-v1-addon-and-classic-ember-cli-macros-support-in-6-0.md +++ b/text/1239-dropping-v1-addon-and-classic-ember-cli-macros-support-in-6-0.md @@ -7,12 +7,12 @@ teams: - data - cli prs: - accepted: + accepted: https://github.com/emberjs/rfcs/pull/1239 project-link: suite: --- -# WarpDrive: Dropping V1 Addon and Classic ember-cli Macros Support in 6.0 +# Dropping V1 Addon and Classic ember-cli Macros Support in 6.0 ## Summary