Serverside Rendering of Vue components
Background
There has been some recent discussion around improving the frontend performance of the GitLab application, some in this issue about setting an OKR for the next quarter: gitlab-com/www-gitlab-com#7201 (closed) (also, see the slack thread linked from that issue for further context).
Following on from that discussion, @andr3 (scalability team frontend counterpart) and I had a call (recorded at https://www.youtube.com/watch?v=e2iccdgrY5s) around the various approaches we can take to reduce the perceived speed of the GitLab application.
While there are several approaches to be considered, we both agreed that, over the long term, the greatest architectural change that can be made to improving the frontend performance of GitLab is to incorporate server-side rendering of our Vue components.
Currently, GitLab relies primarily on client-side rendering of components, with some elements still rendered in HAML. As long as we're doing this, matching the performance of our competitors is going to be difficult. This technology provides a huge boost in perceived performance.
For example: compare the HTML that arrives for similar pages on GitLab.com and GitHub.com: gitlab-com/www-gitlab-com#7201 (comment 326374713)
Consider the steps we need to go through to render a page:
- Send HTML response with Javascript script URLs
- Download Javavscript bundles
- Compile Javascript bundles in browser
- Boot application and fetch graphql responses from server
- Render components
Visually, the GitHub page is rendered at point 5 in the first step, when the response is sent from the server. While downloading, compiling and bootstrapping still takes time, it happens without visual changes, so it far more seamless to the user, resulting in the perception of greater performance.
Proposal
Consider using a technology like Hypernova (https://github.com/airbnb/hypernova) to pre-render Vue.js components server side.
Hypernova was developed by Airbnb, and allows them to render Javascript views alongside their Rails application server side.
More reading:
- https://medium.com/airbnb-engineering/operationalizing-node-js-for-server-side-rendering-c5ba718acfc9
- https://medium.com/js-dojo/using-vue-js-with-hypernova-server-ce792dcf1ac7
But what about the servers? Would we need to run nodejs in production.
Yes.
However, there is no reason why we cannot make this an optional component. Self-managed instances that want simplicity can leave this component turned off. Instances that want the best performance could turn it on.
If we built with this model in mind from the beginning, the application should easily be able to handle both mounting pre-rendered components or render the components from scratch. On GitLab.com, we could run the the nodejs process alongside the Ruby process on the web nodes, and gradually enable it on different applications through feature flags.