Integrating React and Phaser 3 Tutorial

Taylor Nodell
3 min readApr 15, 2019

While building a fun little punnett square in React, I wanted to expand to include some visualizations in a game engine. Phaser is one of the top JavaScript based game engines, however I found few resources that combined the most popular front end framework with this game engine. A wrapper exists for Phaser CE but it’s a bit outdated and I wanted to use Phaser 3. And this tutorial gets both running, but isn’t able to run the Preload function. I also followed a webpack tutorial for setting up React manually. Using these resources, these are my steps to get React up with Phaser 3.

Phaser and React Logos

The tech: React, Babel, Webpack, Phaser 3, Node, NPM

Here’s the final template repo.

1) First we’ll clone the Phaser 3 Project template. I use this as the base rather than Create-React-App because we can config the webpack set up, rather than having to eject from Create-React-App.

2) Run npm i path babel-preset-react to install dependencies. The Phaser 3 template comes with babel-core but not the preset for React.

3) Now we’ll need to update our webpack config. In webpack/base.js we’ll add entry and output keys and include rules for JSX and CSS. We’ll also include filename and inject keys for our HtmlWebpackPlugin.

module.exports = {
mode: "development",
devtool: "eval-source-map",
entry: "./src/index.js",
output: {
path: path.resolve("dist"),
filename: "index_bundle.js"
},
module: {
rules: [
{
test: /\.css$/,
use: [{ loader: "style-loader" }, { loader: "css-loader" }]
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: "babel-loader"
},
{
test: [/\.vert$/, /\.frag$/],
use: "raw-loader"
},
{
test: /\.(gif|png|jpe?g|svg|xml)$/i,
use: "file-loader"
}
]
},
plugins: [
new CleanWebpackPlugin(["dist"], {
root: path.resolve(__dirname, "../")
}),
new webpack.DefinePlugin({
CANVAS_RENDERER: JSON.stringify(true),
WEBGL_RENDERER: JSON.stringify(true)
}),
new HtmlWebpackPlugin({
template: "./index.html",
filename: "index.html",
inject: "body"
})
]
};

5) Update .babelrc to include “@babel/preset-react” as a preset. I changed mine to be a .babelrc.js so my editor would automatically format it.

const presets = [
[
"@babel/env",
{
targets: {
browsers: [">0.25%", "not ie 11", "not op_mini all"]
},
modules: false
}
],
"@babel/preset-react"
];
const plugins = [];
module.exports = { presets, plugins };

6) Now we can finally add a React component. Let’s make a folder for those, components/App.jsx.

import React from "react";export default class App extends React.Component {
render() {
return (
<div style={{ textAlign: "center" }}>
<h1>Hello World</h1>
</div>
);
}
}

7) Because src/index.js is our entry point we’ll need to render our component there with ReactDOM.render. From here we can grow our code base both in React and Phaser!

import Phaser from "phaser";
import logoImg from "./assets/logo.png";
import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App.jsx";
const config = {
type: Phaser.AUTO,
parent: "phaser-example",
width: 800,
height: 600,
scene: {
preload: preload,
create: create
}
};
const game = new Phaser.Game(config);function preload() {
this.load.image("logo", logoImg);
}
function create() {
const logo = this.add.image(400, 150, "logo");
this.tweens.add({
targets: logo,
y: 450,
duration: 2000,
ease: "Power2",
yoyo: true,
loop: -1
});
}
ReactDOM.render(<App />, document.getElementById("root"));

And that’s it! Running npm start will open up a browser with the Phaser Logo and your React component at the top of the page.

Our Page on Localhost:8080

--

--

Taylor Nodell

Developer. Musician. Naturalist. Traveler. In any order. @tayloredtotaylor