Skip to content

fix(build): make the web build loadable outside Node - #837

Open
niravanu wants to merge 1 commit into
google:mainfrom
niravanu:fix/web-build-runs-on-edge-runtimes
Open

fix(build): make the web build loadable outside Node#837
niravanu wants to merge 1 commit into
google:mainfrom
niravanu:fix/web-build-runs-on-edge-runtimes

Conversation

@niravanu

Copy link
Copy Markdown

dist/web could only be loaded by Node, so @google/adk could not be bundled for a browser, a worker, or any edge runtime. Two independent causes, both in core/build.js.

The createRequire banner was applied to the browser build. The shim exists so an ESM build can reach a CommonJS dependency, which is a Node concern, but the condition was format === 'esm' — and the web build is browser + esm. Every one of the 256 files in dist/web therefore opened with import {createRequire} from 'module', including leaf modules with no Node dependency at all. Bundlers targeting a browser resolve that as a missing package and stop.

The browser target included Safari 11, which predates async generators. esbuild lowered them, and its lowering of yield* super.method() emits __yieldStar(super.method()) in a scope where super is a syntax error, so models/apigee_llm.js did not parse. Safari 11 was never really supported — the library uses async generators throughout, and they are ES2018. The target only claimed it.

Measured before and after with wrangler, since Cloudflare Workers is the case that fails hardest:

before ✘ [ERROR] Unexpected "super"
dist/web/models/apigee_llm.js:142:25
after Total Upload: 4652.19 KiB / gzip: 795.49 KiB

And it runs, not merely builds: a Workflow with two FunctionNodes joining into a JoinNode, plus a RequestInput, constructed inside workerd and answering 200.

Adds a regression test. It asserts the two specific failures — no createRequire anywhere in dist/web, and every file parses — and deliberately does not assert that nothing imports a Node builtin, because several modules legitimately do (file_artifact_service, unsafe_local_code_executor, local_environment, skills/loader, a2a/*) and are only reached by importing them. The banner was different in kind: it was on everything. The test skips when dist/web has not been built, and it fails on the previous build and passes on this one.

The rest of the suite imports src, which is why neither of these was visible to it.

Please ensure you have read the contribution guide before creating a pull request.

Link to Issue or Description of Change

1. Link to an existing issue (if applicable):

  • Closes: #issue_number
  • Related: #issue_number

2. Or, if no issue exists, describe the change:

If applicable, please follow the issue templates to provide as much detail as
possible.

Problem:
A clear and concise description of what the problem is.

Solution:
A clear and concise description of what you want to happen and why you choose
this solution.

Testing Plan

Please describe the tests that you ran to verify your changes. This is required
for all PRs that are not small documentation or typo fixes.

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally.

Please include a summary of passed npm test results.

Manual End-to-End (E2E) Tests:

Please provide instructions on how to manually test your changes, including any
necessary setup or configuration. Please provide logs or screenshots to help
reviewers better understand the fix.

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules.

Additional context

Add any other context or screenshots about the feature request here.

`dist/web` could only be loaded by Node, so `@google/adk` could not be
bundled for a browser, a worker, or any edge runtime. Two independent
causes, both in `core/build.js`.

**The createRequire banner was applied to the browser build.** The shim
exists so an ESM build can reach a CommonJS dependency, which is a Node
concern, but the condition was `format === 'esm'` — and the web build is
browser + esm. Every one of the 256 files in `dist/web` therefore opened
with `import {createRequire} from 'module'`, including leaf modules with
no Node dependency at all. Bundlers targeting a browser resolve that as
a missing package and stop.

**The browser target included Safari 11, which predates async
generators.** esbuild lowered them, and its lowering of
`yield* super.method()` emits `__yieldStar(super.method())` in a scope
where `super` is a syntax error, so `models/apigee_llm.js` did not parse.
Safari 11 was never really supported — the library uses async generators
throughout, and they are ES2018. The target only claimed it.

Measured before and after with wrangler, since Cloudflare Workers is the
case that fails hardest:

  before   ✘ [ERROR] Unexpected "super"
             dist/web/models/apigee_llm.js:142:25
  after    Total Upload: 4652.19 KiB / gzip: 795.49 KiB

And it runs, not merely builds: a Workflow with two FunctionNodes joining
into a JoinNode, plus a RequestInput, constructed inside workerd and
answering 200.

Adds a regression test. It asserts the two specific failures — no
`createRequire` anywhere in `dist/web`, and every file parses — and
deliberately does not assert that nothing imports a Node builtin, because
several modules legitimately do (`file_artifact_service`,
`unsafe_local_code_executor`, `local_environment`, `skills/loader`,
`a2a/*`) and are only reached by importing them. The banner was different
in kind: it was on everything. The test skips when `dist/web` has not
been built, and it fails on the previous build and passes on this one.

The rest of the suite imports `src`, which is why neither of these was
visible to it.
@google-cla

google-cla Bot commented Aug 27, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@kalenkevich kalenkevich left a comment

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.

Totally make sense, thanks!

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