Love.js: Don't Call It A Post-Mortem

This is a post to sum up my current thoughts on the state of Love.js.

Love.js is an Emscripten port of LÖVE and it's dependencies. It's goal is to allow developers to package their games to be deployed to the web. I want to start by saying how proud I am of it as a project. That we can run the Lua interpreter inside of a JavaScript interpreter and have things work as well and as quickly as they do is a testament to the superb engineering effort of both the Emscripten and the LÖVE devs. Despite the amount of time I've spent with it, it still seems like a little bit of magic to me.

But, as it stands right now, I would not push for browsers to be one of the targeted platforms for LÖVE. There's no one reason why I feel that this project can't be made ready for stable releases. It's all the little things. The lack of threads, the way browsers stumble a little when you first try to load a JS blob over 5MB in size, and being locked into TCP for networking: these are, to my mind, the main offenders. What follows is a brief overview of these issues and how I hope they will be resolved.

A lack of threads means that any asset decoding needs to happen in the main thread, further impacting runtime performance or increasing the initial loading time and memory footprint. Threads are also a core API exposed by the LÖVE framework that can't be reified currently. I have hope that Mozilla's work on shared memory and atomics in Firefox will eventually yield a working thread model with shared memory that would help with this problem but, at the time of this writing, the shared memory spec is still stabilizing.

The size of the binary is something that can't be entirely avoided. LÖVE does a lot to help facilitate easy development and with that comes a significant number of dependencies including SDL2, freetype, libogg, libvorbis, Lua, OpenAL, OpenGL, zlib, libmodplug, mpg123 (for mp3 decoding) and physfs. This is not even considering the modified Box2D, networking, text and math libraries. Loading such a substantial codebase into memory is something that operating systems are more equipped to do than browsers, particularly since JS engines must still parse and convert this code to bytecode to execute it. Should Web Assembly help alleviate some of these problems, I think that the switch would be straightforward since the existing build system uses Emscripten's CMake tooling. Time will tell as Web Assembly's spec is also still actively being developed.

Finally, it would be really nice to have access to proper UDP networking in the browser. I suppose there might not be much call for UDP outside of games but it's perhaps the biggest stumbling block that doesn't seem to have any major push toward resolution. In general, though, networking from a browser is going to be so different from what you'd do on any other platform that this seems like a smaller issue than the previous two. Between same-origin policy and a lack of UDP socket, my approach to porting games with networking code into Love.js has been just to strip it out entirely. LÖVE is mostly used to prototype small single or local multiplayer games anyway, so this issue has seemed to be of minimal impact.

Those are the major, outstanding project issues for Love.js and they're why I haven't been pushing to get my changes merged into the main project repo. There are smaller issues still outstanding but most of them have solutions or workarounds. Despite all this, I'm very happy with the current state of Love.js and look forward to what better tooling allows me to do with it in the next few years.