Deploying Felgo Games & Apps to the Web

Overview

Felgo allows local development and deployment for the Web with WebAssembly. WebAssembly is a bytecode representation generated from C++ code that is executed inside a virtual machine in web browsers. Most of the recent browser versions of Chrome, Firefox and Safari support running WebAssembly code.

Felgo targets WebAssembly as another Desktop platform. This allows you to target your mobile users via the app stores while running the very same app from a single source code on the Web for the desktop.

Note: Due to mobile browser support of WebAssembly, running the WebAssembly target on mobile devices is currently not intended.

This guide describes how to deploy Felgo apps & games for the Web.

Live Code Reloading on Web During development

You can test your code on the browser without any additional setup, using the Felgo Live Client for Web. You can open the Web Live Client with the "Web Client" tab within Felgo Live Server.

Add Felgo Packages for Web Platform

The Felgo installer only installs the packages for your desktop system initially. You can add other packages via the Maintenance Tool. The Maintenance Tool is located at the installation directory of your Felgo SDK. The executable is called SDKMaintenanceTool.

Run this application and select Add or remove components and then choose the platforms you want to add.

Build Your App or Game

Felgo for WebAssembly uses the Emscripten compiler to build C++ portable applications to target browsers with WebAssembly support.

Prepare your Project

WebAssembly builds are created statically, which means all libraries and files required by your app are packaged within the binary format for WebAssembly (.wasm).

WASM apps can only access files that are bundled via the qrc file system. In contrast to building for Desktop or the mobile platforms, you also have to add your asset files (images, fonts, etc) to the qrc file.

Therefore, make sure to add all your QML & JavaScript files and assets to your qrc file before building your project. To learn how to do that, have a look at the publishing guide.

Build Your Project

Qt Creator ships with an experimental plugin to build a WASM app. Currently, the recommended way is to build your apps from the command line, as described with the following steps:

Build on Windows

1. Open a cmd terminal and add the MinGW compiler directory to the path:

 set PATH=<Path to your Felgo SDK>\Tools\mingw730_32\bin;%PATH%

2. Set compiler environment variables:

 <Path to your Felgo SDK>\Felgo\wasm_32\emsdk\emsdk_env.bat

3. Create your build dir outside your project folder (shadow build directory):

 mkdir build-wasm && cd build-wasm

4. Run qmake:

 <Path to your Felgo SDK>\Felgo\wasm_32\bin\qmake.exe <Project Path>

5. Run `make` to build the wasm file:

 mingw32-make.exe

Build on macOS and Linux

1. Open a Terminal and setup the environment:

 source <Path to your Felgo SDK>/Felgo/wasm_32/emsdk/emsdk_env.sh

2. Create a build directory outside your project folder (shadow build directory):

 mkdir build-wasm && cd build-wasm

3. Run qmake

 <Path to your Felgo SDK>/Felgo/wasm_32/bin/qmake <PROJECT_PATH>

3. Run `make` to build the wasm file

 make

Note: You can run make -j <nproc>, being nproc the number of cores you have available to speed up the process running in parallel build

Build Output

The build process will generate multiple files:

  • index.html: The default Felgo entry point of your application for the browser. You can customize the HTML to your needs
  • index.js: This file contains the WebAssembly module corresponding to your application.
  • index.wasm: The actual WebAssembly binary of your application, including all files that you added to the qrc file, i.e. QML & JavaScript files and assets like images or fonts.
  • qtloader.js: Provides APIs for application life-cycle management like the loading screen or crash and process exit handling.
  • felgo-logo.png: Splash image used for the default HTML.

Test Your App

Opening the generated index.html file directly in your web browser won’t work because loading WASM modules is only supported via a web server. To run your app, you therefore need to load it from a (local) web server.

For local testing, you can run the included web server by executing the command emrun --browser chrome index.html from within the dist folder in your terminal.

Note: You can also run python -m SimpleHTTPServer or ruby -run -e httpd -- -p 8000 in your build directory to use Python or Ruby to serve your build.

Publish Your App or Game to the Web

In order to publish your app or game, you need to use a static web server. Most common servers do just fine, but there are a few considerations to deliver the best user experience:

Set Content-Type header

In order for browsers to download and compile your binary files quicker, they can take advantage of streamed compilation. This only works if browsers know that they are dealing with a WebAssembly binary in advance. To tell them, you need to set the Content-Type: application/wasm header.

Enable Caching

Make sure that your server is sending the ETag and Cache-Control headers. This way, subsequent opens of the website load the wasm files from cache. A new download is only triggered if you have updated your .wasm file (you can set the highest max-age value possible for your wasm files).

Enable gzip Compression

Qt .wasm files might be a bit larger than what most users would expect. To reduce download time, enable compression at your server configuration. We suggest using gzip but you can also try brotli (bear in mind that is less widely supported). You can also compress the .wasm file beforehand using gzip, this reduces the download size up to half the original file size and therefore greatly improves the download time.

CORS

Cross Origin restrictions apply to all requests made by your application, just like those to browser-side JavaScript requests. Make sure your backend and media servers are set accordingly to your website host domain serving your app.

HTML Canvas

With the default HTML, the target canvas uses the full size of the browser window. You can modify the HTML to your needs to define a canvas that coexists with different HTML elements, like in the example illustrated below.

Current Limitations

File System and Networking

Your app runs in a sandboxed environment inside the browser that has the same restrictions as the rest of your website, such as:

  • Mixed content: If your website is hosted using HTTPS, browsers might block or warn about mixed content requests. To prevent such warnings, make sure to use HTTPS instead of HTTP for your network requests.
  • File system access:
    • There is no direct file system access to the host machine, you can access files or download from your application using the QFileDialog::getOpenFileContent() and QFileDialog::saveFileContent() C++ APIs.
    • The WebAssembly compiler provides alternatives for applications that make use of the file system:
      • MEMFS: There is an in-memory file system used for temporary file access. This API is synchronous and can be accessed with the default Qt File implementation anywhere outside the /home/web_user directory, e.g. /tmp.
      • IDBFS: There is also support for persistent file storage on top of the “Browser Indexed DB”. This file system is asynchronous and full synchronization is done before the application starts, as well as write synchronization at the end of application execution. You can use persistent storage in the /home/web_user directory provided by the IDBFS.
      • Note that MEMFS and IDBFS are emulations of a Linux/POSIX file system and do not correspond in any way to the underlying host FS, as you might expect.

Felgo

Following NativeUtils QML APIs are not supported with WebAssembly:

Qt Modules

The WebAssembly platform currently does not ship with the following Qt modules and QML components:

  • DataVisualization
  • WebView
  • Multimedia: No playback of audio/video within WebAssembly

Following Qt modules can be used but functionality is not implemented for WebAssembly:

  • Location & Positioning
  • Sensors

JavaScript Environment

It is important to note that there are two different JavaScript environments in place, the one provided by the browser your app is running on and the one implemented in the QML JavaScript engine. All of your QML/JavaScript code runs inside the WebAssembly sandbox and can’t directly interact with the browser-side JavaScript, unless you write specific C++ code to handle the communication.

Others

Due to the current implementation of Qt, WebAssembly applications report the platform as “unix” in the platform.os string. Instead of that you can use the “system.isPlatform(System.Wasm)” check in your QML code to get to know if you are running your app as a WebAssembly build.

Destructors are not called on app exit, due to the way WebAssembly main loop is implemented, C++ destructors execution is not not guaranteed on application exit.

Since the WebAssembly platform is single threaded, the implementation for the QML/JS Engine WorkerScript component is synchronous.

Nested event loops are not supported. Applications should not call e.g. QDialog::exec() or create a new QEventLoop object. Otherwise the app stops execution and you need to reload your browser.

Applications do not have access to system fonts. Font files must be distributed with the app in qrc files.

Qt renders application content to a canvas element, and does not use native DOM elements. Therefore, accessibility tools like screen readers are not supported and text inputs do not necessarily trigger virtual keyboards.

Official WebAssembly Guides

Voted #1 for:

  • Easiest to learn
  • Most time saving
  • Best support

Develop Cross-Platform Apps and Games 50% Faster!

  • Voted the best supported, most time-saving and easiest to learn cross-platform development tool
  • Based on the Qt framework, with native performance and appearance on all platforms including iOS and Android
  • Offers a variety of plugins to monetize, analyze and engage users
FREE!
create apps
create games
cross platform
native performance
3rd party services
game network
multiplayer
level editor
easiest to learn
biggest time saving
best support