Skip to content

refactor: inline example runtime urls#8746

Merged
kpal81xd merged 27 commits into
mainfrom
example-runtime-url-cleanup
May 21, 2026
Merged

refactor: inline example runtime urls#8746
kpal81xd merged 27 commits into
mainfrom
example-runtime-url-cleanup

Conversation

@kpal81xd
Copy link
Copy Markdown
Contributor

@kpal81xd kpal81xd commented May 18, 2026

Description

This updates how examples are authored and cleaned up in the examples browser. The goal is for new examples to look like normal ESM modules: use static imports for code/text sidecars, use simple runtime URL strings for files loaded by the engine, and let the iframe loader clean up PlayCanvas apps automatically. It also consolidates the author-facing examples browser context into examples/context, so examples import data and deviceType from one place. It also migrates example config metadata to multiline // @config blocks with // @flag entries.

Example config format:

// @config
//
// <div style="text-align:center">
//     <div>(<b>WASD</b>) Move</div>
//     <div>(<b>Space</b>) Jump</div>
//     <div>(<b>Mouse</b>) Look</div>
// </div>
//
// @flag HIDDEN
// @flag ENGINE=performance

Files Moved

Area Before After What example authors should use
Shared WASM files examples/src/lib/ examples/assets/wasm/ Runtime URLs such as ./assets/wasm/draco/draco.wasm.js and ./assets/wasm/twgsl/twgsl.js
Ammo examples/src/lib/ammo/* examples/assets/wasm/ammo/* ./assets/wasm/ammo/...
Basis examples/src/lib/basis/* examples/assets/wasm/basis/* ./assets/wasm/basis/...
Draco examples/src/lib/draco/* examples/assets/wasm/draco/* ./assets/wasm/draco/...
GLSLang examples/src/lib/glslang/* examples/assets/wasm/glslang/* ./assets/wasm/glslang/glslang.js
TWGSL examples/src/lib/twgsl/* examples/assets/wasm/twgsl/* ./assets/wasm/twgsl/twgsl.js

Importing And Runtime URLs

Use case Before After
PlayCanvas engine Browser-injected globals / helper imports import * as pc from 'playcanvas';
Example browser context import { data } from 'examples/observer'; plus import { deviceType } from 'examples/utils'; import { data, deviceType } from 'examples/context';
Shared example modules fileImport(...) or helper-generated URLs import ... from 'examples/assets/...';
Shared engine script modules Runtime helper paths when module code was needed import ... from 'playcanvas/scripts/...';
Legacy ES5 helper Shared loadES5 from examples/utils Define one-off helpers locally when needed, or prefer real ESM imports
Local sidecar modules localImport('module.mjs') import { helper } from './module.mjs';
Local sidecar text Vite-specific raw imports such as ./shader.frag?raw import shader from './shader.frag';
Local JSON Manual fetch / helper imports import data from './data.json';
Engine-loaded assets Generated *Url imports or rootPath + 'assets/...' Plain runtime strings such as ./assets/models/statue.glb
Engine-loaded scripts Generated *Url imports or rootPath + 'scripts/...' Plain runtime strings such as ./scripts/camera/orbit-camera.js
WASM support files rootPath + 'static/lib/...' / examples/src/lib/... Plain runtime strings under ./assets/wasm/...

Runtime URL rule of thumb:

  • Use ./assets/... for files served from examples/assets/.
  • Use ./scripts/... for shared engine scripts when they are loaded as script assets.
  • Use examples/context for examples browser-provided state: data and the selected deviceType.
  • Use real ESM imports for JavaScript modules and local sidecar files.

Cleanup And Destroy Conditions

Scenario Before After
Standard example app Examples exported app with export { app }; so the loader could destroy it Examples just create a top-level app; no export is needed
Standard app lookup Loader used module.app from the imported example module Loader falls back to pc.AppBase.getApplication('application-canvas')
Hot reload / iframe destroy Loader destroyed only the exported app Loader destroys every registered PlayCanvas app attached to a canvas under #appInner
Extra canvases, such as multi-app Example-specific destroy code had to remove additional apps/canvases Loader removes extra canvases after destroying their registered apps; application-canvas is preserved
export { destroy }; Could be used for app cleanup and non-app cleanup Keep it only for non-app resources: timers, RAFs, DOM overlays, processors, benchmark UI, or other resources outside AppBase.destroy()
User-facing remove controls Example handlers removed individual apps while the example was running Those handlers stay; loader cleanup only handles full reload/destroy of the iframe-owned apps

Public API

No engine API changes. This only changes examples browser authoring conventions and loader cleanup behavior. The author-facing examples modules are now consolidated under examples/context; examples/observer and examples/utils are no longer part of the examples import map.

Manual Testing

  • Started the examples browser development server and confirmed misc_multi-app.html uses <base href="../static/">.
  • Confirmed /static/assets/wasm/twgsl/twgsl.js and /static/assets/wasm/glslang/glslang.js return 200.
  • Confirmed examples import data and deviceType from examples/context, and examples/context exposes only those two values.
  • Opened misc/hello-world, hot reloaded, and confirmed window.ready === true with the app and canvas registered.
  • Opened misc/multi-app, added and removed an app, hot reloaded, and confirmed old extra canvases/apps were gone and new apps were registered.
  • Opened gaussian-splatting/benchmark, hot reloaded, and confirmed its benchmark UI was not duplicated.

Checklist

  • I have read the contributing guidelines
  • My code follows the project coding standards
  • This PR focuses on a single change

@mvaligursky
Copy link
Copy Markdown
Contributor

Much nicer!
I assume the files still show up in the tabs / can be modified?

@kpal81xd
Copy link
Copy Markdown
Contributor Author

Much nicer! I assume the files still show up in the tabs / can be modified?

Yep all works exactly the same

@kpal81xd kpal81xd force-pushed the example-runtime-url-cleanup branch from efd6d09 to 68e342a Compare May 19, 2026 10:18
@kpal81xd kpal81xd force-pushed the example-runtime-url-cleanup branch from 68e342a to d86fdf4 Compare May 19, 2026 10:29
@kpal81xd kpal81xd added the enhancement Request for a new feature label May 19, 2026
@kpal81xd kpal81xd marked this pull request as ready for review May 19, 2026 14:07
@kpal81xd kpal81xd force-pushed the example-runtime-url-cleanup branch from 32506f2 to e65d0b8 Compare May 19, 2026 14:07
@kpal81xd kpal81xd force-pushed the example-runtime-url-cleanup branch from bd399c5 to 38fa4a2 Compare May 21, 2026 12:58
@kpal81xd kpal81xd merged commit c7914a2 into main May 21, 2026
8 checks passed
@kpal81xd kpal81xd deleted the example-runtime-url-cleanup branch May 21, 2026 12:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Request for a new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants