Looking into Scala.js

Looking into Scala.js

Looking into Scala.js

Introduction

yoda

This blog post was created to see how Scala.js is holding on and having some fun with programming. I decided to do a simple mini-game using Scala.js and Three.js libraries.

I will explore Scala.js from a practical perspective. You’ll see the perks of using typed languages in frontend. We are also going to take a look under the hood and see some generated JS code. Finally, I’m going to present some advantages and disadvantages of Scala.js and try to answer the question: Is Scala.js production ready?

I encourage you to read this blog post about Scala.js basics first, but it’s not required.

My inspiration for the game was: https://oos.moxiecode.com/js_webgl/xwing/

Source code of my game: https://github.com/andrjew/scalac-fighter/tree/0.1.1

Why Three.js library? I chose it because I’m familiar with it and I knew that it’ll provide me things I need. Three.js is in fact 3D library and initially I also wanted to create a 3D mini game, but it ended up being 2D ;)

The game

This is how the game looks like:
game

And here you can have some fun and play: https://fighter.scalac.io

I know the game is far from perfection. I’ve stopped developing it when the game became playable. That leave much place for improvements. If you want to add some features to the game or just see how it is to program in Scala.js, just grab the code from Github: https://github.com/andrjew/scalac-fighter.

About the project

We had our fun time, now let’s see how the game looks from the inside.
Firstly please see project structure to understand basic concept: project-tree
I believe architecture here is not too hard. Every class is quite self-explanatory. The most of game’s logic is located inside Game class.

One thing, which I want to notice is the force of having typed language like Scala. The advantage over JS is that I’m unable to accidentally confuse Bulletwith EnemyShip. In JavaScript such mistake is highly possible and can be hard to debug. In Scala, the type system protects me form this kind of misery.
Moreover, please look at this example from Game.scala:

https://gist.github.com/andrjew/59baaf7a08f14ef40695

This code is responsible for moving objects on each animation frame. But I only want to move object that are self-moving (like bullet), so I created a special SelfMoving trait. As a result I can use pattern matching on game’s objects collection and easily move only self-moving items.

The Type System Strikes Back

Another example will be from Main.scala:

https://gist.github.com/andrjew/fb85689d877224eab699

This piece’s task is to react on player’s mouse movements. For capturing mouse movements I’ve used the jQuery library (wrapper). We can see that Scala.js allows us to use anonymous function just like in Scala.

But something more intriguing is happening here. Our anonymous function take parameter of type JQueryEventObject and unfortunately this type doesn’t have event.clientX field, which I need to move player’s ship. This happens because jQuery event is normalized into jQuery abstraction (see this for details). The funny thing is that the field clientX is there (we can observe it while debugging JS), but we can’t see it, because we’re limited with JQueryEventObject trait.

Sadly attempt of using partial function:

https://gist.github.com/andrjew/717a869a6f2f5376c712

won’t succeed, there is an compile error: The argument types of an anonymous function must be fully known. (SLS 8.5).

Neither below mixing works:

https://gist.github.com/andrjew/031cb8126b344aa31169

The parameter type must be exactly JQueryEventObject class or it’s ancestor.

And not surprisingly pattern matching also fails:

https://gist.github.com/andrjew/28462cac6cf6c936a690

This fails because proposed case will never be matched.

All of our Scala forces has failed. We need to use the dark side of the Force:

https://gist.github.com/andrjew/e9f44e25e30abe1372fe

Solution is to cast event: JQueryEventObject object to DOM’s standard MouseEvent which is represented in Scala.js under org.scalajs.dom.MouseEvent class. This works because in JS runtime this object is in a fact an MouseEvent.

Maybe some persons sense some more disturbance here. If yes, then you’re right. The dark side reveals again:

https://gist.github.com/andrjew/f94002e34a42702e401e

One of the most terrifying power of the dark side, the mutability attacks!

The mutable trap

trap

Please see following example from GameScene class:

https://gist.github.com/andrjew/a00af7caf8d24826c3f9

As you can observe this class is not written in immutable style. Adding a new object to GameScene doesn’t create new instance of itself. Instead of that it is changing it’s inner state. Yes, I know. We don’t like mutability, but there is a cause of this state.

Please notice that scene is instance of threejs.Scene. This scala class is just a direct wrapper for Three.js (JavaScript) implementation. Because of that you can look at scene.add(gameObject.object3d) as it was pure JS code, which you can’t change. Unfortunately JS implementation of function scene.add(...) is mutable and this is something I had to accept.

Three.js library was designed in mutable way and this is not a mistake or bad thing. The problem occurs when we want to write our application in immutable/functional way as we used to do in Scala.

Unfortunately when using a Three.js under the hood we are not able to achieve this easily.
Image a situation when you want to do a fully immutable copy of my game. You would have to create each frame of animation (each object) from zero. This is possible, but performance impact would be probably too big. Please notice that creating a new object in javascript can absorb a way more time than using setter.

It’s possible to fight JS libraries mutability, but when taking Scala.js (in immutable style) into consideration always remember about possible extra work overhead and performance issues.

With current state of JavaScript itself and it’s libraries, personally I thing fighting with mutability is pointless. For me it’s something you will need to accept when deciding to use Scala.js. If you can’t beat them, join them.

Where is JS ?

In this paragraph I want to make you aware of what happening after compiling Scala code to JavaScript. So let’s see where we can find generated JS code and how does it looks like after compilation.

After compiling to javascript with sbt fastOptJS command, you can find output files in scalac-fighter/target/scala-2.11 directory. The most important file there is scalac-fighter-fastopt.js. This file includes compiled game code and also Scala.js related code. That’s making the file 17 783 lines long :(

This is unnecessary obstacle and makes reading compiled code even harder. I’m aware that not every person will explore gendered code, but some compiler option providing my code and Scala.js separately would be great.

Let’s take a quick look into some example:

Scala:

https://gist.github.com/andrjew/725cbf146bf6e08c6fe7

JavaScript (formatted by me):

https://gist.github.com/andrjew/d68f8e884a662c64e942

As we can see the generated code is not very eye-friendly. Function name in JS is 5 times longer than in Scala.
Probably __s_Option fragment is responsible for noticing scala’s Optionhere, but this is only my hunch.
Next part,org_denigma_threejs_Vector3 is just fully qualified class name for Three.js object.
Quite mysterious function is $uD, but we can find it in generated code and this is:

https://gist.github.com/andrjew/419d9d0e8d95c33bd810

So mystery is solved ;] this is just a function that ensure Double type. Further we see how Scala.js compiler handle Scala’s Option by using simple if-elseplus isEmpty__Z function.

Should I care about generated JS ?

Generally I think not, but it’s good to know what’s going on ;]
Even tough reading compiled Scala.js code is hard, looking into it will make You better understand how Scala.js works and what limitations it could have.

Conclusions

Things I like:

  • Easy to start working with
  • Many, ready to use JS libraries facades for Scala.js. I was very positively surprised to find a Three.js facade
  • Good alternative for person who must do something in JS, but can’t look at it :)
  • You can debug Scala code directly from browser. This really works and it’s great! This is possible thanks to sourcemap mechanism. To try this just open developer tools in browser and then in source section debug Scala code like you normally debug JS code.
  • Of course type system (safety, clarity and other)
  • Support for autocomplete and other perks of IDE

Things I dislike:

  • You can’t escape from mutable JS libraries
  • Generated code is rather hard to read (but not impossible)
  • Possible more inconveniences like the one with JQueryEventObjectand MouseEvent

Can I use Scala.js in production ?

windu

Probably this is the most important question. Is it production ready ?
Unfortunately I’m not going to give you an easy answer. More proper question is: Does Scala.js do the things that I require? Does it complete my requirements ?.

As for me, Scala.js worked fine in my mini project. I’ve created working game in language I like with no bigger problems. It was really pleasant and fun experience. Personally I feel very positive about this technology. I believe that it’s no longer just an experiment, but aspire to be an alternative for JavaScript, especially for persons from backend world.

In summary my answer won’t be just Yes or No. Instead of that I will provide a checklist, that will help you to know if Scala.js is something you can use.

Checklist (before using in production):

  • Absolutely MUST do a recognition by yourself.
    • Learn how Scala.js works, what are the differences between Scala and Scala.js.
    • Read docs(Scala.js pages) and other articles(Hands-onScala.js)
    • Try Scala.js in applications / projects:
      – write some mini project
      – try to break/hack Scala.js
      – take my project and just have some fun with it ;)
  • Check availability of Scala.js facades for JavaScript libraries you are going to use. Many people do Scala.js wrappers for most popular libraries. If however you can’t find wrapper, you’ll have to do one by yourself. See more details here.
  • Look into generated JS code to be aware what’s really going on.

Credits

Thanks to:

  • Scala.js team. I want to say that I admire you for work that they already done. Combining these two languages is not easy for sure. Keep fighting the good fight.
  • Three.js team – I’m enthusiast of this library for quite long time.
  • Creator of facade for Three.js library: https://github.com/antonkulaga/threejs-facade.
  • Patryk Jażdżewski for help with project and game code.

May the force be with you :)

Do you like this post? Want to stay updated? Follow us on Twitter or subscribe to our Feed.

See also

Download e-book:

Scalac Case Study Book

Download now

Authors

Andrzej Janczak

I am a passionate Scala backend developer with Java background. Dreaming about perfect and simple solutions with clean code, but is also aware that sometimes the saying "better done than perfect" applies. Love to struggle with complicated, nontrivial problems because there is a huge satisfaction and knowledge that comes at the end.

Latest Blogposts

17.04.2024 / By  Michał Szajkowski

Mocking Libraries can be your doom

Test Automations

Test automation is great. Nowadays, it’s become a crucial part of basically any software development process. And at the unit test level it is often a necessity to mimic a foreign service or other dependencies you want to isolate from. So in such a case, using a mock library should be an obvious choice that […]

04.04.2024 / By  Aleksander Rainko

Scala 3 Data Transformation Library: ducktape 0.2.0.

Scala 3 Data Transformation Library: Ducktape 2.0

Introduction: Is ducktape still all duct tape under the hood? Or, why are macros so cool that I’m basically rewriting it for the third time? Before I go off talking about the insides of the library, let’s first touch base on what ducktape actually is, its Github page describes it as this: Automatic and customizable […]

28.03.2024 / By  Matylda Kamińska

Scalendar April 2024

scala conferences april 2024

Event-driven Newsletter Another month full of packed events, not only around Scala conferences in April 2024 but also Frontend Development, and Software Architecture—all set to give you a treasure trove of learning and networking opportunities. There’re online and real-world events that you can join in order to meet colleagues and experts from all over the […]

software product development

Need a successful project?

Estimate project