Bundling your phaser.js game with esbuild

It’s been two years since I wrote an article about how to bundle phaser projects using parcel. Eventually I needed to find a solution that fit my needs better and ended up trying all the big players in bundling right now. After a couple of weeks with s…


This content originally appeared on DEV Community and was authored by Kevin Potschien

It's been two years since I wrote an article about how to bundle phaser projects using parcel. Eventually I needed to find a solution that fit my needs better and ended up trying all the big players in bundling right now. After a couple of weeks with sticking to esbuild, here's a final write up on my current workflow, that reliably works for every new project I work on.

Setting up the project

Skip this part if you're familiar with how to set up a basic project in your IDE and continue with Adding esbuild

The Basics

Using mkdir create an empty folder - but don't worry, you can simply create a folder as you normally would with your system.

After opening this folder with our IDE, initialize a new project. In my case, I use yarn init in the terminal of VS Code, using the latest stable version of Yarn.

Once you're done, add Phaser as a dependency:
yarn add phaser and a couple of dev dependencies using yarn add -D esbuild esbuild-plugin-copy @types/node

Also, add "type": "module" to your package.json file, as we want to take advantage of EcmaScript Modules.

Structure

Start off by creating a src folder, that will hold all of our essential game files as well as a folder called scripts, also located in our root directory. In there, create a folder called assets to hold our music, spritesheets, and more. We also want a file called app.ts that comes with a simple scene.

// app.ts
import Phaser from 'phaser';

class GameScene extends Phaser.Scene {
    preload() {
        this.load.image('coin', './assets/coin.png');
    }

    create() {
        this.add
            .text(this.sys.canvas.width / 2, 300, 'Hello World')
            .setOrigin(0.5, 0.5);

        this.add.image(this.sys.canvas.width / 2, 250, 'coin');
    }
}

const game = new Phaser.Game({
    type: Phaser.AUTO,
    scale: {
        mode: Phaser.Scale.ScaleModes.FIT,
        autoCenter: Phaser.Scale.Center.CENTER_BOTH,
    },
    width: 800,
    height: 600,
    parent: 'game',
    scene: GameScene,
});

and an index.html as our entry point:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Phaser-Esbuild-Template</title>
        <style>
            * {
                margin: 0;
                padding: 0;
                box-sizing: border-box;
            }
        </style>
    </head>
    <body>
        <div id="game"></div>
        <script src="./app.js" type="module"></script>
    </body>
</html>

Adding esbuild

Esbuild's customization gives us different ways of handling the bundled output: We will focus on creating a dist folder that contains a index.html file as our main entry point. There is a way to only output your game as a single, minified js file. In this case, handling assets gets slightly more complex. I will leave an example as a branch in the final repo.

Watch Mode

In order to work on our game locally, we need a script that watches for changes and reloads our browser.

Add a script to the package.json that will run a file located in the scripts folder:

    "scripts": {
        "start": "DEBUG=true node scripts/esbuild.start.js"
    }

esbuild.start.js contains the following:

import esbuild from 'esbuild';
import { copy } from 'esbuild-plugin-copy';

const context = await esbuild.context({
    logLevel: 'info',
    entryPoints: ['src/app.ts', 'src/index.html'],
    bundle: true,
    outdir: 'dist',
    sourcemap: true,
    platform: 'browser',
    loader: {
        '.html': 'copy',
    },
    format: 'esm',
    define: {
        'process.env.DEBUG': `"${process.env.DEBUG}"`,
    },
    plugins: [
        copy({
            assets: {
                from: ['./src/assets/**/*'],
                to: ['./assets'],
            },
            watch: true,
        }),
    ],
});

const result = await context.rebuild();

await context.watch();

await context.serve({ servedir: './dist' });

At this point, running the yarn start command should give you a live preview of your game running. If it's not, make sure you read the console's output carefully or leave a comment here and I'll try to help you out.

Build

Just like with the Watch Mode, we add an additional script to the package.json:

    "scripts": {
        "start": "DEBUG=true node scripts/esbuild.start.js",
        "build": "rm -rf ./dist && node scripts/esbuild.config.js"
"
    }

this will clean up our dist directory before every new build and make sure no extra files slip into the dist directory.

add the esbuild.config.js file with this content:

// esbuild.config.js
import esbuild from 'esbuild';
import { copy } from 'esbuild-plugin-copy';

esbuild.build({
    logLevel: 'info',
    entryPoints: [
        { out: 'app', in: 'src/app.ts' },
        { out: 'index', in: 'src/index.html' },
    ],
    bundle: true,
    outdir: 'dist',

    sourcemap: false,
    minify: true,
    legalComments: 'none',
    loader: {
        '.html': 'copy',
    },
    define: {
        'process.env.DEBUG': `"${process.env.DEBUG}"`,
    },
    plugins: [
        copy({
            assets: {
                from: ['./src/assets/**/*'],
                to: ['./assets'],
            },
            watch: true,
        }),
    ],
});

Most of these settings should be self-explanatory, but make sure to consult esbuild's documentation if you want adjust everything to your needs.

The final repo is available on my GitHub.

Let me know in the comments if there's any hickups or problems!


This content originally appeared on DEV Community and was authored by Kevin Potschien


Print Share Comment Cite Upload Translate Updates
APA

Kevin Potschien | Sciencx (2024-09-16T08:09:12+00:00) Bundling your phaser.js game with esbuild. Retrieved from https://www.scien.cx/2024/09/16/bundling-your-phaser-js-game-with-esbuild/

MLA
" » Bundling your phaser.js game with esbuild." Kevin Potschien | Sciencx - Monday September 16, 2024, https://www.scien.cx/2024/09/16/bundling-your-phaser-js-game-with-esbuild/
HARVARD
Kevin Potschien | Sciencx Monday September 16, 2024 » Bundling your phaser.js game with esbuild., viewed ,<https://www.scien.cx/2024/09/16/bundling-your-phaser-js-game-with-esbuild/>
VANCOUVER
Kevin Potschien | Sciencx - » Bundling your phaser.js game with esbuild. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/09/16/bundling-your-phaser-js-game-with-esbuild/
CHICAGO
" » Bundling your phaser.js game with esbuild." Kevin Potschien | Sciencx - Accessed . https://www.scien.cx/2024/09/16/bundling-your-phaser-js-game-with-esbuild/
IEEE
" » Bundling your phaser.js game with esbuild." Kevin Potschien | Sciencx [Online]. Available: https://www.scien.cx/2024/09/16/bundling-your-phaser-js-game-with-esbuild/. [Accessed: ]
rf:citation
» Bundling your phaser.js game with esbuild | Kevin Potschien | Sciencx | https://www.scien.cx/2024/09/16/bundling-your-phaser-js-game-with-esbuild/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.