novablocks · 2022React Migration
5 min read
When I got onboarded, the game's frontend was built with a mix of Rails views, Hyperscript, and a mix of vanilla JavaScript. Making UI updates were hard and there were bugs popping up due to state being managed by both Rails and vanilla JavaScript.
The architecture was something like this:

I then raised my concerns in regards to the codebase architecture and suggested on how we can improve it. In which, they agreed. By the end, the refactoring the codebase was worth it since it increased the velocity of building UIs by a ten-fold.
Problem
- The some view-state is being managed by Rails, while some is being managed by JavaScript.
This leads to confusion for the developers as to where to put the state and the need to switch between front-end coding patterns. Moreover, with this approach, the passing of the state between the two - Rails and JavaScript, led to unexpected bugs. Moreover, since Rails is managing the view layer, the game-engine files needed to be compiled and committed to git for production use.
- Using Vanilla JavaScript to build the UI is difficult to scale.
It's becoming harder and harder to build UIs while keeping the state in-synced when using vanilla JavaScript. Moreover, with this approach, it's taking more time to develop features. Read more about Why Modern Js Frameworks Exist.
Solution
Use a declarative framework for the UI and use Rails as an API instead.
1. Using a declarative framework - ReactJS
We came into a consensus that we need to use a declarative framework in order to move fast and let JavaScript manage the state. With this, we went on to research as to what framework/library to use, narrowing down our choices we ended up with these options:
Svelte
I studied a bit as to how Svelte work and made some demos as to how it works and in intergrating it. Moreover, we can use Svelte Cubed, which is a component library for building ThreeJS scene graphs in Svelte apps, in the future.


Moreover, I learned that re-assignment triggers re-render in Svelte which I think might be a problem since there are times when don't want that.
In the video, you can see how the re-rendering is triggered. Tho at that time, there might be a solution I'm not aware of like adding dependencies for reactive parts like how useEffect
in ReactJS works.
VueJS
Sadly, I had a hard time making VueJS work well with rollup since most of it suggest using Vite.
It is just outputting something like this:

Moreover, rollup-plugin-vue is no longer maintained saying "This is no longer maintained. Use Vite and @vitejs/plugin-vue instead".
Due to the time constraint, we decided to pass over VueJS for now since it is hard to integrate Vue with our current setup which uses plain Rollup due to the lack of roll up support. Moreover, Vite uses rollup under the hood but in order to switch to it I need to understand first how the engine code is being compiled since it has a lot of customization in its rollup config like resolution for the draco loader, code that generates a hash version and the like. So in order to properly migrate to VueJS, I might need to study more in regards to the module bundler works.
ReactJS
I might be biased because ReactJS is one of my core tech stack, but upon working with it, it was easy to integrate the current codebase with it. Moreover, since I know why React Re-renders, it is easier to be in control as to when to trigger the re-render. Lastly, there's a huge community around it and has a React Renderer for ThreeJS called React Three Fiber.
Conclusion
So in the end, we first tried using Svelte because the learning curve is not that steep unlike React so that it would be easier for the other team members to adapt. But we stopped when we came into a discussion that it is much faster to build stuff on top of ReactJS due to the huge community around it which allows us access to a lot of open source libraries. The team needed to get the first version out so using ReactJS, which is also my specialty, became our choice.
It took me a month to refactor almost everything from vanilla JS to ReactJS. The only features that hasn't been migrated yet are the chat and debug features which we de-prioritize for now in favor of features critical for the investor demos.
Fast forward to couple of months, I've built multiple features with it that helped in raising investor funds. And the whole team felt the huge benefits of using a declarative framework as opposed to using vanilla JS.
2. From Monolith to using Rails as an API server.
Coming Soon.