mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-14 19:27:05 -04:00
- #174: the file names are fixed (effectcraft_web.js, effectcraft_web_bg.wasm, worker.js, sw.js…), not content-hashed, so the guide's year-long immutable caching kept returning visitors on the old release after an in-place upgrade. The guide, nginx example, _headers and .htaccess now revalidate (no-cache) the .wasm, .js and index.html, and suggest a versioned path for longer caching. The file table lists the real files. - #180: the .wasm is about 58 MB (17 MB gzip, 10 MB Brotli) for v0.3.1, not 13 MB / 5 MB; docs/web.md's 38 MB figure is updated too. - #165: preferences live in the origin's browser storage (OPFS, IndexedDB or memory), not localStorage. - #164: relative URLs come from the page itself (and package.sh's check), not a Trunk.toml that doesn't exist. The iframe example's title no longer says image editor. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
b09f06f417
commit
120c7ec4e1
4 files changed
+37
-26
No files matched your search
@@ -7,10 +7,8 @@ AddType text/javascript .js
|
||||
</IfModule>
|
||||
|
||||
<IfModule mod_headers.c>
|
||||
<FilesMatch "\.(wasm|js)$">
|
||||
Header set Cache-Control "public, max-age=31536000, immutable"
|
||||
</FilesMatch>
|
||||
<FilesMatch "^index\.html$">
|
||||
# The file names don't change between releases: revalidate them (HOSTING.md).
|
||||
<FilesMatch "(\.(wasm|js)|^index\.html)$">
|
||||
Header set Cache-Control "no-cache"
|
||||
</FilesMatch>
|
||||
</IfModule>
|
||||
+27
-17
@@ -6,29 +6,38 @@ static site in `effectcraft-web-<version>/`:
|
||||
| File | What it is |
|
||||
|---|---|
|
||||
| `index.html` | The page. It loads everything through relative URLs. |
|
||||
| `effectcraft-web-<hash>.js` | wasm-bindgen glue (generated, ES module) |
|
||||
| `effectcraft-web-<hash>_bg.wasm` | The app, about 13 MB, or 5 MB with compression |
|
||||
| `effectcraft_web.js` | wasm-bindgen glue (generated, ES module) |
|
||||
| `effectcraft_web_bg.wasm` | The app: about 58 MB, about 17 MB with gzip and 10 MB with Brotli (v0.3.1) |
|
||||
| `snippets/…/js/host.js` | Browser glue (storage, audio, workers) |
|
||||
| `worker.js`, `audio-worklet.js` | Render and frame workers, and audio playback |
|
||||
| `sw.js`, `manifest.webmanifest`, icons | Offline install: the service worker and the app manifest |
|
||||
| `_headers`, `.htaccess` | Sample header rules for Netlify/Cloudflare Pages and Apache |
|
||||
|
||||
There is no server-side code. Upload the folder's contents anywhere that serves static files.
|
||||
|
||||
## Any path works
|
||||
|
||||
All URLs in `index.html` are relative (`public_url = "./"` in `apps/effectcraft-web/Trunk.toml`),
|
||||
so the site works at a domain root (`https://example.com/`), under a prefix
|
||||
(`https://example.com/tools/effectcraft/`) and from a CDN bucket. The asset names carry a content
|
||||
hash, so they can be cached forever. Only `index.html` needs revalidation.
|
||||
All URLs in `index.html` are relative: the page is written that way
|
||||
(`apps/effectcraft-web/web/index.html`), and `package.sh` refuses a build with root-absolute
|
||||
URLs. So the site works at a domain root (`https://example.com/`), under a prefix
|
||||
(`https://example.com/tools/effectcraft/`) and from a CDN bucket.
|
||||
|
||||
The file names are the same in every release (`effectcraft_web_bg.wasm` and so on), so browsers
|
||||
must revalidate them: a long-lived cache would keep returning visitors on the old version after
|
||||
you upgrade in place. Revalidation is cheap (an unchanged file answers `304 Not Modified`), and
|
||||
the service worker keeps the app for offline use after the first visit. To cache the files for
|
||||
longer, serve each release from its own versioned path (`/effectcraft/0.4.0/`).
|
||||
|
||||
## Required server settings
|
||||
|
||||
- **MIME type:** serve `.wasm` as `application/wasm`. Browsers refuse to stream-compile it under
|
||||
any other type, and the app then loads slowly or not at all. Serve `.js` as `text/javascript`.
|
||||
Most hosts already do both. For nginx, check that `mime.types` has `application/wasm wasm;`.
|
||||
- **Compression:** turn on gzip or Brotli for `.wasm`, `.js` and `.html`. That takes the
|
||||
download from about 13 MB to about 5 MB. You can also precompress (`brotli -k *.wasm`) and let
|
||||
the server send `Content-Encoding: br`.
|
||||
- **Caching:** `Cache-Control: public, max-age=31536000, immutable` on the hashed `.wasm` and
|
||||
`.js` files, and `no-cache` on `index.html`.
|
||||
- **Compression:** turn on gzip or Brotli for `.wasm`, `.js` and `.html`. For v0.3.1 that takes
|
||||
the download from about 58 MB to about 17 MB (gzip) or 10 MB (Brotli). You can also
|
||||
precompress (`brotli -k *.wasm`) and let the server send `Content-Encoding: br`.
|
||||
- **Caching:** `Cache-Control: no-cache` (revalidate) on `index.html`, `sw.js` and the `.wasm`
|
||||
and `.js` files, since their names don't change between releases (see above).
|
||||
- **HTTPS:** WebGPU (and the clipboard) only work in a secure context, which means `https://`
|
||||
or `http://localhost`. Over plain HTTP elsewhere, the app falls back to WebGL2.
|
||||
- **No special isolation headers:** EffectCraft doesn't use `SharedArrayBuffer`, so it doesn't
|
||||
@@ -43,8 +52,7 @@ location /effectcraft/ {
|
||||
types { application/wasm wasm; text/javascript js; text/html html; }
|
||||
gzip on;
|
||||
gzip_types application/wasm text/javascript text/html;
|
||||
location ~* \.(wasm|js)$ { add_header Cache-Control "public, max-age=31536000, immutable"; }
|
||||
location ~* index\.html$ { add_header Cache-Control "no-cache"; }
|
||||
location ~* (\.(wasm|js)|index\.html)$ { add_header Cache-Control "no-cache"; }
|
||||
}
|
||||
```
|
||||
|
||||
@@ -55,7 +63,7 @@ Local test: `python3 -m http.server 8765` inside the folder, then open http://lo
|
||||
```html
|
||||
<iframe
|
||||
src="https://example.com/effectcraft/"
|
||||
title="EffectCraft image editor"
|
||||
title="EffectCraft"
|
||||
style="width: 100%; height: 720px; border: 0;"
|
||||
allow="fullscreen; clipboard-read; clipboard-write"
|
||||
allowfullscreen>
|
||||
@@ -64,9 +72,11 @@ Local test: `python3 -m http.server 8765` inside the folder, then open http://lo
|
||||
|
||||
- The app fills the iframe and follows its size, so size the iframe and not the app.
|
||||
- Keyboard shortcuts go to the iframe after the user clicks into it, as with any embedded app.
|
||||
- **Cross-origin embeds** work. Preferences are kept in the iframe's `localStorage`. Browsers
|
||||
that partition or block third-party storage may forget them between visits, and the app
|
||||
then starts with defaults.
|
||||
- **Cross-origin embeds** work. Preferences, projects and imported media are kept in the
|
||||
iframe origin's browser storage: the Origin Private File System, else IndexedDB, else memory
|
||||
only (`effectcraft.info().storage.backend` says which; see `docs/web.md` › Persistence).
|
||||
Browsers that partition or block third-party storage may forget them between visits, and the
|
||||
app then starts with defaults.
|
||||
- **Sandboxed iframes** need at least
|
||||
`sandbox="allow-scripts allow-same-origin allow-downloads allow-popups"`. Without
|
||||
`allow-same-origin` there's no storage. Without `allow-downloads`, Save and Export (browser
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
/*
|
||||
X-Content-Type-Options: nosniff
|
||||
|
||||
# The file names don't change between releases: revalidate them (HOSTING.md › Any path works).
|
||||
/*.wasm
|
||||
Content-Type: application/wasm
|
||||
Cache-Control: public, max-age=31536000, immutable
|
||||
Cache-Control: no-cache
|
||||
|
||||
/*.js
|
||||
Cache-Control: public, max-age=31536000, immutable
|
||||
Cache-Control: no-cache
|
||||
|
||||
/index.html
|
||||
Cache-Control: no-cache
|
||||
Reference in new issue
Block a user