Skip to content

feat: replace legacy web explorer preview with Bevy Web - #1502

Merged
gonpombo8 merged 6 commits into
mainfrom
feat/replace-web-explorer-with-bevy-web
Jul 31, 2026
Merged

feat: replace legacy web explorer preview with Bevy Web#1502
gonpombo8 merged 6 commits into
mainfrom
feat/replace-web-explorer-with-bevy-web

Conversation

@gonpombo8

@gonpombo8 gonpombo8 commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Removes the unity-renderer web preview and makes Bevy Web the browser preview path:

What could break

  • Anyone relying on the local web preview URLs (http://localhost:PORT?SCENE_DEBUG_PANEL...) — the local server no longer serves a web client at /; it remains the realm/content server.
  • Smart-wearable web preview relied on the unity web client; wearable endpoints remain but desktop Explorer is now the way to view them.
  • Older published @dcl/sdk versions keep working — they pin their own @dcl/explorer copy.
  • The @dcl/explorer entry still visible in sdk-commands/package-lock.json belongs to the published @dcl/sdk@7.17.0 dev-dep tree and clears on the next release.

How to test

  1. make build, then in a scene: sdk-commands start --web → browser opens https://decentraland.org/bevy-web/?preview=true&realm=http://127.0.0.1:PORT; allow the Chrome "Apps on device" prompt; scene loads and hot-reloads on file changes.
  2. sdk-commands start (no flag) → desktop Explorer deeplink flow unchanged.
  3. npx jest --testPathPattern='kernel-and-renderer-version|test/sdk-commands/commands/start' → passes (28 tests). tsc --noEmit in sdk-commands passes.
  4. Fresh scene install no longer downloads @dcl/explorer (244 MB smaller).

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 28, 2026

Copy link
Copy Markdown

Deploying js-sdk-toolchain with  Cloudflare Pages  Cloudflare Pages

Latest commit: be41563
Status: ✅  Deploy successful!
Preview URL: https://c8d1a08d.js-sdk-toolchain.pages.dev
Branch Preview URL: https://feat-replace-web-explorer-wi.js-sdk-toolchain.pages.dev

View logs

@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Test this pull request

  • The @dcl/sdk package can be tested in scenes by running

    npm install "https://sdk-team-cdn.decentraland.org/@dcl/js-sdk-toolchain/branch/feat/replace-web-explorer-with-bevy-web/dcl-sdk-7.25.1-30635337865.commit-3ff9694.tgz"
  • The @dcl/js-runtime package can be tested in scenes by running

    npm install "https://sdk-team-cdn.decentraland.org/@dcl/js-sdk-toolchain/branch/feat/replace-web-explorer-with-bevy-web/@dcl/js-runtime/dcl-js-runtime-7.25.1-30635337865.commit-3ff9694.tgz"
  • To test with npx init

    export SDK_COMMANDS="https://sdk-team-cdn.decentraland.org/@dcl/js-sdk-toolchain/branch/feat/replace-web-explorer-with-bevy-web/dcl-sdk-commands-7.25.1-30635337865.commit-3ff9694.tgz"
    npx $SDK_COMMANDS init
  • The /changerealm command to test test in-world

    /changerealm https://sdk-team-cdn.decentraland.org/ipfs/feat/replace-web-explorer-with-bevy-web-e2e
    
  • You can preview this build entering:
    https://playground.decentraland.org/?sdk-branch=feat/replace-web-explorer-with-bevy-web

The @dcl/explorer unity web build was a 244MB dependency frozen at an
Aug 2024 snapshot, downloaded on every scene install only to serve the
deprecated --web-explorer preview. Drop it and the preview-server routes
that served it; --web/--bevy-web (now pointing at decentraland.org
instead of .zone) covers browser preview via the hosted Bevy Web client,
with the local server acting as its realm. --web3 and --no-debug remain
declared as no-ops so existing start scripts keep working, and the CLI
prints Chrome Local Network Access guidance since decentraland.org needs
the 'Apps on device' permission to reach localhost.
@eordano
eordano force-pushed the feat/replace-web-explorer-with-bevy-web branch from 2d718be to d74ad02 Compare July 28, 2026 15:19
@eordano

eordano commented Jul 28, 2026

Copy link
Copy Markdown
Member

Just one comment: hot reload doesn't seem to be working

@decentraland-bot decentraland-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review: feat: replace legacy web explorer preview with Bevy Web

Branch: feat/replace-web-explorer-with-bevy-webmain
Files changed: 7 (+42 −167) — net deletion, nice cleanup.

Clean, well-scoped PR that removes the 244 MB Unity web build (@dcl/explorer) and makes Bevy Web the browser preview path. The PR body is thorough and the test updates are correct. One blocking issue with a removed flag that still has downstream consumers.


P1 — Blocks merge

[Consumer breakage] --web-explorer removed from the arg parser will break downstream consumers.

The arg library throws on unknown flags. Removing '--web-explorer': Boolean from declareArgs means any script passing --web-explorer will crash on the next SDK release. At minimum:

Fix: Keep '--web-explorer': Boolean in the args declaration (accepted but ignored), document it as deprecated in the help text like --web3 and --no-debug, and open a follow-up issue/PR on decentraland/docs to update the docs.

P2 — Minor

  1. [Dead code] --explorer-alpha is still declared in args but is now effectively a no-op. The explorerAlpha variable is simply !bevyWeb — the --explorer-alpha flag value is never read. Consider deprecating it in the help text (same pattern as --web3/--no-debug) or removing the declaration if no consumers pass it.

  2. [Naming] explorerAlpha variable is now misleading. It's just !bevyWeb — the name suggests the old alpha explorer distinction that no longer exists. A rename to something like desktopExplorer (or inlining !bevyWeb) would improve readability.

  3. [Pre-existing bug] chokidar unlink handler has wrong callback signature.

    .on('unlink', (_: unknown, file: string) => {
      removeModel(sceneId, file)
    })

    Chokidar's unlink event passes a single argument (path), not (event, path). Here _ captures the path and file is always undefined, making removeModel a no-op (it exits early on isGLTFModel(undefined)). This bug existed before this PR but is now executed unconditionally. Not blocking, but worth fixing while touching this file.

  4. [Docs follow-up] decentraland/docs needs a companion update to replace --web-explorer references with --web/--bevy-web.

Notes

  • @eordano's hot reload comment: The code changes look correct for hot reload — both protobuf and legacy WS messages are now sent unconditionally, which is strictly more coverage than before. The hot reload issue is likely related to Chrome's Local Network Access policy blocking WebSocket connections from decentraland.org to localhost (the PR already adds guidance about this). Worth confirming whether hot reload works once the permission is granted.
  • Security: No new vulnerabilities introduced. The /feature-flags/:file proxy is pre-existing and scoped to feature-flags.decentraland.zone. No secrets, no injection vectors.
  • @dcl/explorer removal from @dcl/sdk: Safe — downstream lockfiles pin their own copy, and the serveStatic consumer is fully removed.
  • CI: All checks still pending at review time (build, test, lint, docs).

Reviewed by Jarvis 🤖 · Requested by Gonzalo Pombo (<@U02EUDGAM6W>) via Slack

@@ -53,7 +53,6 @@ export const args = declareArgs({
'--skip-build': Boolean,
'--data-layer': Boolean,
'--explorer-alpha': Boolean,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[P1] --web-explorer was removed from declareArgs, but decentraland/godot-explorer (scripts/bench/launch_devices.sh) and decentraland/docs still reference it. The arg library throws on unknown flags, so this will crash those scripts on the next SDK release.

Keep it as a deprecated no-op (same pattern as --web3 and --no-debug):

Suggested change
'--explorer-alpha': Boolean,
'--explorer-alpha': Boolean,
'--web-explorer': Boolean, // deprecated no-op, kept for backwards compatibility

@@ -36,17 +33,15 @@ export async function wireFileWatcherToWebSockets(
cwd: projectRoot
})
.on('unlink', (_: unknown, file: string) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[P2] Pre-existing bug: chokidar unlink fires with a single (path) argument, not (event, path). Here _ captures the path and file is always undefined, making removeModel a no-op.

Suggested fix:

Suggested change
.on('unlink', (_: unknown, file: string) => {
.on('unlink', (file: string) => {
removeModel(sceneId, file)
})

@gonpombo8

Copy link
Copy Markdown
Contributor Author

Re: review

P1 (--web-explorer removal breaking consumers): Not valid — the old web explorer is not used anymore. Anything still passing --web-explorer is targeting a client that no longer exists, so keeping the flag around would only hide that. A hard error on the next release surfaces the migration; docs will be updated separately.

P2.1 (--explorer-alpha dead code): The flag can't be removed. The Creator Hub (and possibly other processes) still launch the CLI with --explorer-alpha, and since arg throws on unknown flags, removing the declaration would break those flows. It stays declared and accepted intentionally.

@decentraland-bot decentraland-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Re-review: feat: replace legacy web explorer preview with Bevy Web

Re-reviewed based on the author's feedback on the previous round. No code changes since the last review (latest commit is a merge from main).

Previous findings — updated

  • P1 (--web-explorer removal) Withdrawn. Author's rationale accepted: the old web explorer no longer exists, so a hard error on the next release intentionally surfaces the migration. Keeping the flag as a no-op would hide that scripts are targeting a dead client. Docs update is covered by decentraland/docs#150.

  • P2.1 (--explorer-alpha dead code) Withdrawn. Creator Hub (and possibly other processes) still launch the CLI with --explorer-alpha, so the declaration must stay to avoid breaking those flows.

Remaining P2 (non-blocking)

  1. [Pre-existing bug] chokidar unlink handler has wrong callback signaturefile-watch-notifier.ts:35: chokidar unlink fires with (path), but the handler destructures (_: unknown, file: string), so file is always undefined and removeModel is a no-op. Not introduced by this PR, but worth fixing in a follow-up since it's now executed unconditionally.

Verdict

Approved. Clean, well-scoped removal that drops 244 MB of dead weight. The breaking change is intentional and well-documented. No security issues. CI is still running at review time.


Reviewed by Jarvis 🤖 · Requested by Gonzalo Pombo (<@U02EUDGAM6W>) via Slack

Chokidar's unlink event passes a single (path) argument, not
(event, path). The previous signature (_ : unknown, file: string)
captured the path in _ and left file undefined, making removeModel
a no-op for deleted GLB/GLTF files.
@gonpombo8
gonpombo8 merged commit 0f012e0 into main Jul 31, 2026
8 checks passed
@gonpombo8
gonpombo8 deleted the feat/replace-web-explorer-with-bevy-web branch July 31, 2026 13:43
eordano added a commit that referenced this pull request Aug 3, 2026
Rebased onto main (0f012e0, "replace legacy web explorer preview with
Bevy Web" #1502). The branch's 38 commits are collapsed into one: they
included an entire abgen *sidecar* implementation that later commits
deleted and replaced with the in-process addon, so replaying them would
have meant resolving conflicts in code that does not survive.

sdk-commands start now converts through @dcl/abgen-node — a function
call, not a spawned process — and serves the bundles from the preview
server itself, so there is one origin and no port to coordinate.

Conversion is keyed on a sha256 of the publishable files. Identical
content means the same key, so a request for work already in flight
joins it rather than starting a second, and a run publishes only if its
key is still the one most recently asked for. Results publish by
atomic rename out of a private staging directory, with an advisory lock
and an age-gated sweep, so two previews of one project cannot interleave
bundle files into a directory a reader is about to serve.

Two conflicts with #1502, both resolved in main's favour:

- wireFileWatcherToWebSockets: main now sends updateScene
  unconditionally, because the legacy JSON protocol is the only one Bevy
  and Godot understand. This branch had gated it behind a desktopClient
  flag, which would have regressed Bevy Web, so the flag is dropped and
  only the onProjectChanged invalidation is layered on.
- its 'unlink' handler: main's (file) signature is correct; this branch
  read (_, file), which left file undefined, since chokidar emits the
  path as the first argument.

52/52 green across the four start-command suites.
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.

4 participants