fix: IOEXT-1726 aio app dev fails when project package.json has "type": "module"#231
Merged
Merged
Conversation
…oad as CJS Webpack emits the action bundle with libraryTarget: 'commonjs2', but Node walks up to the closest package.json to decide the module type for the bundled index.js. If the user's project package.json sets "type": "module", Node parses the CJS bundle as ESM and aio-cli-plugin-app-dev's require()-based loader fails with "<action> action not found, or does not export main", breaking aio app dev for every web action. aio app deploy is unaffected because the deployed bundle runs in an OpenWhisk Node container where there is no parent package.json to interfere. Drop a sibling package.json in the webpack temp output that pins the bundle to CommonJS, regardless of the project's module type. This fixes the single-file (webpack-bundled) action case. Directory-style actions written in native ESM remain a separate, larger problem requiring a loader refactor in aio-cli-plugin-app-dev.
There was a problem hiding this comment.
🤖 PR Reviewer
The fix is well-targeted and the comment clearly explains the reasoning. The implementation is straightforward and the test adequately covers the new behavior. One minor concern is that fs.writeJsonSync is called outside the Promise returned by the webpack callback, meaning it runs after the Promise resolves but is not awaited or error-handled — however since writeJsonSync is synchronous and fs-extra throws synchronously on error, this is acceptable. Overall the code is clean and correct.
✅ LGTM! This PR looks good to merge.
💡 How to re-trigger
Comment /review or /pr-reviewer on this PR
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes IOEXT-1726: every web action returns
400 "<action> action not found, or does not export main"fromaio app devwhen the user's projectpackage.jsondeclares"type": "module".aio app deployis unaffected.Reproduction (with
@adobe/aio-cli@11.1.0,@adobe/aio-lib-runtime@7.3.0, Node 22 or 24):Root cause
prepareToBuildActionwrites a webpack bundle to<dist>/<pkg>/<action>-temp/index.jswithlibraryTarget: 'commonjs2', but does not drop a siblingpackage.json. Node decides the bundle's module type by walking up to the closestpackage.json, which is the user's project root. When that file has"type": "module", Node parses the CommonJS bundle as ESM.@adobe/aio-cli-plugin-app-dev'sdefaultActionLoaderinrun-dev.jscallsrequire(actionPath), which throws, gets caught, and surfaces the misleading"<action> action not found, or does not export main"message.aio app deployis unaffected because the deployed bundle runs in an OpenWhisk Node container with no parentpackage.jsonto interfere.Fix
After webpack writes the bundle, drop a sibling
package.jsonpinning the bundle to CommonJS. This is a one-line change insideprepareToBuildAction's non-directory branch:The sibling is the closest ancestor
package.jsonNode finds when resolving the bundledindex.js, so it wins regardless of the project's setting. The change is invisible to deploy: the OpenWhisk Node runtime treats bundled.jsactions as CJS already, and an explicit{ type: 'commonjs' }is consistent with the bundle's actual format.Scope
This fixes single-file (webpack-bundled) actions, which is the case in the bug report. Directory-style actions written in ESM would also need the dev plugin's loader to switch from
require()to dynamicimport(); tracked separately as ACNA-4604.Test plan
test/build.actions.test.jsassertsprepareToBuildActionwrites<temp>/package.jsonwith{ type: 'commonjs' }next to the bundledindex.jscurl /info→ HTTP 400,"info action not found, or does not export main"✗curl /info→ HTTP 200 ✓package.jsonin the zip just makes the bundle's CJS-ness explicit.memfsPOSIX virtual filesystemRisk
Very low. The change only touches output produced for webpack-bundled (single-file) actions. Existing tests continue to pass; the new test locks in the contract.