Support type=module v2 addons - #718
Conversation
Ember addons need their .js files to be interpreted the same way whether or not the addon's package.json says "type": "module". Without this, webpack gives strict ESM treatment to .js files in v2 addons that say type=module, which breaks them in two ways: 1. Default-importing one of the CommonJS/AMD modules that we externalize (like @ember/component/template-only, or any v1 addon) yields the module's exports object rather than its default export, because strict ESM importers don't get the __esModule interop. At runtime this shows up as errors like "_ember_component_template_only is not a function" (embroider-build/embroider#1774) or "Attempted to load a component, but there wasn't a component manager associated with the definition". 2. Import specifiers must be fully-specified, so directory imports and the relative extensionless es-compat2 import that @embroider/macros emits for importSync() fail to resolve (embroider-build/embroider#1672). This adds a module rule that opts .js files owned by v2 addons back into webpack's regular javascript/auto handling, which is exactly the treatment every non-type=module v2 addon already gets. Part of the type=module quest: embroider-build/embroider#1773 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Note on the red CI: all including suites this PR doesn't touch ( The new Happy to take a stab at getting the test matrix onto ember-source 7 in a separate PR if that's welcome. |
A v1 addon dependency is externalized to the runtime AMD loader, so default-importing it from a strict-ESM file is one of the interop shapes the javascript/auto rule exists to fix. Verified load-bearing: with only fullySpecified:false (no type override), the component renders and the importSync module fail with the strict-ESM interop and runtime-require errors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Added explicit coverage for the "type=module v2 addon depends on a v1 addon" case: Also ran a sharper control locally: with only (For completeness: |
Part of the type=module quest issue: embroider-build/embroider#1773
Problem
When a v2 addon sets
"type": "module"in its package.json, webpack applies strict ESM semantics to all of the addon's.jsfiles, which breaks them in two ways that non-type=module addons never hit:Lost
__esModuleinterop for externalized modules. Default-importing one of the CommonJS/AMD modules we externalize (like@ember/component/template-only,@glimmer/componentwhen it's a v1 addon, or any other v1 addon) yields the module's exports object instead of its default export, because webpack (correctly, per spec) skips the__esModuleinterop for strict-ESM importers. At runtime this shows up as:_ember_component_template_only__WEBPACK_IMPORTED_MODULE_x__ is not a function([type=module] _ember_component_template_only is not a function embroider#1774)Attempted to load a component, but there wasn't a component manager associated with the definition. The definition was: ObjectFully-specified resolution. Import specifiers inside the addon must carry file extensions, so directory imports (
./lib→./lib/index.js) fail, and so does the relative extensionlesses-compat2import that@embroider/macrosemits when it compilesimportSync()(importSyncbreaks the builds of apps consuming type=module packages embroider#1672):Solution
Add a webpack module rule that opts
.jsfiles owned by v2 addons back intotype: 'javascript/auto'withresolve: { fullySpecified: false }. That is exactly the treatment every non-type=module v2 addon already gets (their.jsfiles default tojavascript/autobecause their package.json has notypefield), so type=module addons now behave identically to all other v2 addons. Packages that aren't ember addons are unaffected and keep spec-compliant strict ESM behavior.Testing
v2-addon-type-module-test.tswith atype=modulev2 addon covering: a template-only component, a@glimmer/componentsubclass, an internal directory import, andimportSync()from@embroider/macros. All four fail without the fix and pass with it (releaseandreleaseWithModules;beta/canaryare skipped because rendering a component from a v2 addon is broken there even without type=module — same reasonv2-addon-test.tsskips them).v2-addon-test.tsandimport-sync-test.ts(release scenarios incl. fastboot) all pass.app-auto-import-lib-one-template-only-component,app-auto-import-lib-glimmer-component, andapp-auto-import-lib-import-syncapps all pass.🤖 Generated with Claude Code