Preact Support

Gameface supports preact.js - a virtual DOM JavaScript library. The quickest way to get started with Preact is to use a command-line tool. Gameface supports project created or served using Preact CLI v10.

Please note, that only the Simple template is fully supported in Gameface.

Getting started

Installation & Creating a Project

Follow the installation instructions to install it. Installation requirements include:

  • Node 18.15.0
  • Npm 9.5.0

After you install preact-cli open a console (such as Git Bash) and type:

After you install preact-cli, open a console (such as Git Bash) and type preact-cli create simple if you installed preact-cli globally, or npx preact-cli create simple if you did it locally.

Running the Project

Development Server with Live Reload

  1. Open the project’s package.json file add make the following changes:

    • Add the packages required by Gameface:

      "devDependencies": {
      +   "postmessage-polyfill": "^1.0.0",
      +   "whatwg-fetch": "^3.6.2",
      +   "cross-env": "^7.0.3"
      }
      
    • Replace the “build”, “serve” and “dev” commands with these:

      -    "build": "cross-env NODE_OPTIONS=--openssl-legacy-provider preact build",
      -    "serve": "sirv build --port 8080 --cors --single",
      -    "dev": "cross-env NODE_OPTIONS=--openssl-legacy-provider preact watch",
      +    "build": "cross-env NODE_OPTIONS=--openssl-legacy-provider preact build --no-prerender'",
      +    "serve": "sirv build --port 8080 --cors --single --host 127.0.0.1",
      +    "dev": "cross-env NODE_OPTIONS=--openssl-legacy-provider preact watch --host 127.0.0.1",
      

    Run npm i again to install the newly added dependencies.

  2. Next open the application’s main file - the index.js located in the src folder and add the following polyfills:

    import { pm } from 'postmessage-polyfill';
    import { fetch as fetchPolyfill } from 'whatwg-fetch';
    
    const originalInterval = window.setInterval;
    window.setInterval = function(callback, delay = 0) {
        return originalInterval(callback, delay);
    }
    
    window.postMessage = function (message) {
        pm({
            type: message.type,
            origin: 'http://127.0.0.1/:8080',
            target: window,
            data: message,
        });
    };
    
  3. After that create a preact.config.js file in the root of the project and add the following code:

    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    /**
    * Function that mutates the original webpack config.
    * Supports asynchronous changes when a promise is returned (or it's an async function).
    *
    * @param {import('preact-cli').Config} config - original webpack config
    * @param {import('preact-cli').Env} env - current environment and options pass to the CLI
    * @param {import('preact-cli').Helpers} helpers - object with useful helpers for working with the webpack config
    * @param {Record<string, unknown>} options - this is mainly relevant for plugins (will always be empty in the config), default to an empty object
    */
    export default (config, env, helpers, options) => {
        const { isWatch, source } = env;
        let rules = helpers.getRulesByMatchingFile(config, 'src/style.css')
    
        while (rules.length) {
            config.module.rules.splice(rules[0].index, 1)
            rules = helpers.getRulesByMatchingFile(config, 'src/style.css')
        }
    
        config.module.rules.push({
            // User styles
            test: /\.(p?css|less|s[ac]ss|styl)$/,
            include: [source('components'), source('routes')],
            use: [
                isWatch
                    ? require.resolve('style-loader')
                    : MiniCssExtractPlugin.loader,
                {
                    loader: require.resolve('css-loader'),
                    options: {
                        modules: {
                            localIdentName: '[local]__[hash:base64:5]',
                        },
                        importLoaders: 1,
                        sourceMap: true,
                    },
                },
                {
                    loader: require.resolve('postcss-loader'),
                    options: {
                        sourceMap: true,
                        postcssOptions: {
                            plugins: config.postcssPlugins,
                        },
                    },
                },
            ],
        }, {
            // External / `node_module` styles
            test: /\.(p?css|less|s[ac]ss|styl)$/,
            exclude: [source('components'), source('routes')],
            use: [{
                loader: require.resolve('style-loader'),
                options: {
                    injectType: 'linkTag',
                },
            },
            { loader: require.resolve('file-loader') },
            ],
            sideEffects: true,
        });
    };
    

    This will overwrite the default Webpack configuration that is built in preact-cli. We need to do this in order to provide the correct environment for Gameface. It uses the Webpack config helpers API. For more information refer to the documentation.

  4. Execute npm run dev. This command will start a development server with live reload.

  5. Open the Player.bat file with a text editor and set the URL argument to localhost:<port>. The final result should look like this:

    `start "Player" /d   "%wd%" "..\Player\Player.exe" --player "--url=http://localhost:8080/"`
    
  6. Run the Player.bat - it will load the newly created preact application. If you make any changes to wither code or styles the watcher will rebuild the app and reload the Player.

If you see a JS Error: webpack-internal:///../node_modules/webpack-dev-server/client/utils/sendMessage.js:12: TypeError: self.postMessage is not a function message simply refresh the player. This happens because sometimes the Webpack development server tries to send a message before the polyfill is loaded.

Production Build with HTTP Server

Use the npm run build command to create production build. After that use the npm run serve command to serve the build.