COMMUNITY

Haxe + Javascript workflow

I would like to know what is the proper way to work with haxe + js.

I understand about how to call javascript libraries from haxe. But there is a problem when we’re thinking about some specific flow: the webpack one.

So, basically, the common javascript flow was:

Initialize a npm project, create a webpack config, Include into webpack any specific library, include your code, start the build server and then you just maintain that.

What baout coding with haxe? How would the workflow occur?

Basically just replace the step “write JS code” by “write Haxe code and generate JS code”

Should I then just include the haxe output into webpack for processing?

Here’s an example of using three.js from haxe

Rather than webpack I use esbuild

How it works is the three js externs use @:jsRequire so they’re imported via require() and esbuild bundles all the requires into a single file

To build the project you call haxe build.hxml, this generates a js file called main.js but it also has a -cmd arg that executes esbuild to do our bundling, replacing the require() calls

It also include config for live reload editing

The three.js externs were generated with dts2hx:

npm install dts2hx three @types/three
npx dts2hx three -noGlobal

So, my current flow is:

Having a imports.js files which I declare a function:

function expose(obj, as)
{
    var wnd = window || globalThis;
    if(typeof wnd[as] === "undefined")
        wnd[as] = obj;
}

Then I just call:
expose(require("phaser"), "Phaser");
So this file is composed by just requiring js stuff and exporting them to the global scope for haxe can access.

Just call esbuild imports.js --sourcemap --outfile=dist/vendor.bundle.js
So basically, using esbuild for the JS dependencies and build.hxml for the main code

Sounds like you’ve got it down now

Here’s a Phaser example project with automatic externs in case there’s useful bits in there for you

  1. I definitely recommend finding a solution without webpack, unless you’re actually making use of a significant portion of all the features it brings.
  2. Personally, I am a big fan of esbuild - especially its crazy performance. From my own experience I must warn you however that the output it produces is not always compatible with the JavaScriptCore of iOS 11, which is the stock OS of the still rather popular iPhone X. Just two weeks ago I had to remove it from a project. I haven’t yet had time to investigate when this occurs (because frankly it’s easier to just switch to another minifier), but while I recommend esbuild, this is something to keep an eye on.
  3. Something like a game engine doesn’t change very often. It’s best not to bundle it with your game to improve loading speed for returning users. For an unmodified piece of JavaScript, Chrome (and I most other browser too) can load the JITted code from cache - skipping parsing, compilation and optimization. The setup can be as simple as <script src="phaser.{phaserVersion}.min.js></script><script src="game.{gameVersion}.min.js" /></script> in your HTML file. Or you can even make the phaser script async and let the game script wait for it do download while perhaps also executing other startup tasks (e.g. connecting to the game server). Instead of fumbling with scripts you can also figure out a way to handle this with ES6 dynamic imports using a bundler that supports those, if you can determine that this actually reduces complexity for your project.

After some research I’ve finally found --target which IMO has a relatively optimistic default, but in any case, setting it to safari11 fixed things for me. Leaving this here in case someone runs into a similar problem :wink: