Repository navigation
Publishing to the Web
raylib-miniscript runs in a web browser, too. This page explains how to build the web version of your game, test it, and put it on a web server, and how to bundle your game's files into a file package so the page loads faster.
You need the Emscripten SDK, either installed in the project root as emsdk/ or linked there. Then, from the project root:
scripts/build-web.sh
This produces a build-web folder containing:
| File | What it is |
|---|---|
raylib-miniscript.html |
the page that hosts the game |
raylib-miniscript.js, raylib-miniscript.wasm
|
the engine |
index.html |
a redirect to raylib-miniscript.html, so the folder's plain URL works |
assets/ |
a link to your project's assets folder (main.ms, imported modules, images, sounds, and so on), not a copy, so the page always sees your latest files |
Browsers won't run the page straight from your disk (a file:// URL); it has to come from a web server. Python's built-in one is fine for testing:
cd build-web
python3 -m http.server 8000
Then open http://localhost:8000. Leave the server running while you work; after a rebuild, or after editing anything in assets, just reload the page.
The engine always starts by running assets/main.ms. There are two ways to get that file, and everything else your game reads, into the browser.
The page fetches each file from the server when the game first asks for it: the main script, each import, and each image, sound, font or shader. To publish, upload the whole build-web folder, including the files in assets/. Since build-web/assets is a link, copy the folder in a way that follows it, such as cp -RL build-web mygame or rsync -aL build-web/ server:mygame/; plain cp -R, rsync -a and most zip tools copy only the link itself, which won't work on the server.
That's one network request per file. import is the costly part: it looks for a module in each folder on the import path in turn (by default, the main script's folder and then its lib folder), and each place it isn't found is a wasted request that returns "404 Not Found". A game with dozens of modules can make hundreds of requests before its title screen appears. Each request is fast on your own machine, but over the internet they add up.
A file package bundles your entire assets folder into a single file, game.data, along with a small loader script, game.data.js. When the page opens, the loader downloads game.data in one request and unpacks it into the browser's memory, before your game starts. From then on, every file your game reads comes straight from memory, with no network requests at all.
(The package is an Emscripten feature. The in-memory "disk" it unpacks into is the one Emscripten gives every web program in place of a real file system.)
| Loose files | File package | |
|---|---|---|
| Requests to start the game | one per file, plus misses for every import
|
one |
| Files download | when first needed | all of them, before the game starts |
| Best for | a few files; large media the game might never use | many modules or small assets; anything you're publishing |
| After changing a file | just reload | re-run scripts/package-web.sh, then reload |
Most finished games are better off with a package. The main exception is a game with a lot of large media, such as long music tracks or video, which would make players wait at a blank screen while it all downloads. With a package there's no way to leave those files out and fetch them later (see the rules below).
Loose files are often handier while you're still developing, since an edit to a script takes effect as soon as you reload.
After scripts/build-web.sh, run:
scripts/package-web.sh
This:
- packages your
assetsfolder intobuild-web/game.dataandbuild-web/game.data.js(skipping hidden files such as.DS_Store); - adds the line
<script src="game.data.js"></script>tobuild-web/raylib-miniscript.html, just before the engine's script tag.
To package a different folder, or write the package somewhere else, give their paths:
scripts/package-web.sh path/to/mygame/assets path/to/output
Whatever the folder is called on your disk, the game sees its contents as assets/.
Run it again after every build-web.sh: the build rewrites the page, which removes the loader line. (Running it twice is harmless; it won't add the line again.) Run it after you change any game file, too, since the package is a snapshot.
To publish, upload raylib-miniscript.html, raylib-miniscript.js, raylib-miniscript.wasm, game.data, game.data.js, and (if you want the short URL) index.html. The assets/ folder is not needed.
If you host the game in a page of your own rather than the one the build generates, add the loader yourself. It must come after the script that defines var Module, and before the engine script:
<script>
var Module = { /* ... */ };
</script>
<script src="game.data.js"></script>
<script async src="raylib-miniscript.js"></script>-
All or nothing. Once a package is loaded, the engine never fetches a file over the network. A file that isn't in the package doesn't exist, as far as the game is concerned:
importreports "library not found",LoadTextureand friends fail as they would for any missing file, andFileExistsreturns 0. You can't package some files and leave the rest loose. -
It has to be your
assetsfolder. The engine decides whether a package is loaded with one check, made once at startup: is there anassetsfolder in memory?package-web.shalways unpacks toassets. If you run Emscripten's packager yourself, use--preload yourfolder@/assets; a package unpacked anywhere else is ignored, and files are fetched as usual. -
importsearches the same folders as without a package, just in memory, so your import paths don't change. -
FileExistsandDirectoryExistssee the package. Without a package they can only see files your game has created during this session (next rule), since they can't ask the server. -
Saved files vanish on reload.
ExportImage,TakeScreenshotand similar functions write into the same in-memory file system, whether or not you use a package. Your game can load those files back during the session, but they disappear when the page is reloaded, and the player can't download them.
-
The page says "Not found in the file package: assets/main.ms". A package loaded, but it has no
main.msat its top level. Check that you packaged the right folder:main.msmust be directly inside it, not in a subfolder. -
The game never starts; the canvas just stays black. The loader probably couldn't download
game.data. Open the browser's developer console (usually F12, or Cmd-Option-J on a Mac) and look for an error naminggame.data; most likely it isn't next to the page on the server. -
Your changes don't show up. Re-run
scripts/package-web.sh, then reload. If the old version still appears, the browser is probably showing a cached copy ofgame.data; do a hard reload (Shift-Reload, or Cmd-Shift-R on a Mac). -
A module or asset is "not found", but works on desktop. With a package, the file has to be inside the packaged folder. The desktop build can reach files outside it (for example, through a
/usrdisk you've mounted); the web build can't.