Achieving 90+ Mobile Web Performance at Tokopedia
Tokopedia is one of the largest e-commerce platforms in Indonesia. Our users can virtually search for any products they might want to buy at Tokopedia. One thing we have noticed is that new users often found out about Tokopedia when they are searching through the web; sometimes, using their mobile devices. We have implemented various technologies to help users enter our mobile web with ease. One of our approach was to utilise PWA + AMP, you can read more about this at this article.
After some time, a couple of our folks (Dendi Sunardi and Kelvin Mijaya) came back from Chrome Dev Summit 2018, all inspired and filled with knowledge to share. One of the things that we ended up pursuing and experimenting on further is SvelteJS. We found the idea very interesting, a framework that compiles to vanilla JS.
It’s basically as fast as vanilla JS, which makes sense because it is vanilla JS — just vanilla JS that you didn’t have to write. — Svelte blog
“Whoa, that sounds great!”
Svelte also supports server-side rendering, therefore eliminating our concerns regarding SEO. It is way less mature than React though. This also reflects in the community; it is not as massive as React, for sure. But for a landing page, we thought it would be great for the job. We then were faced with a task to decide whether to use AMP or Svelte for our landing page. Anton Saputro, our Product Owner, gave us the liberty to choose which technology to use for this purpose. After weighing the pros and cons, we ended up deciding to go with Svelte.
And thus begin the next phase…
We discussed and came up with a high-level design of how we would integrate this new landing page seamlessly with our already existing React app. We want users to visit this new landing page, for their first visit to Tokopedia. This new landing page should be blazing fast, while maintaining the look and feel of our existing app. It would also install service worker in the background, which will precache the assets needed for our React app, so when our user navigates further, they would seamlessly go into our React app.
With that done, we started exploring SvelteJS and tried to get a working homepage as a proof of concept. Creating and integrating this new service with our existing monorepo wasn’t that hard. We managed to have our minimum working new homepage ready in a little bit over 2 weeks. A lot of the time was actually spent on researching which technology to use, identifying parts where it’s possible to save on bundle size, meetings with stakeholders for product team, data tracking team (big thanks to Marthino Tri Yuda!), and SEO team and basically lots of trials and errors.
We ended up using Svelte to render our UI components, svelte/store (Svelte own Store implementation) for state management, and Emotion for our CSS-in-JS solution. The reason to use svelte/store was mainly to keep our bundle size small. Emotion was used because our engineers use react-emotion on a daily basis, so it helps to reduce the barrier to entry for further contributors to the service. We also dynamically load polyfills on the client side only if necessary. This helped us to reduce our bundle size further.
This is great because new users can get into Tokopedia in a very short time, while the service worker is precaching other assets in the background should the user choose to navigate further into the site.
Using Test My Site tool made by Google, we managed to achieve 0s load time on 4G connection! I am not sure why the rating doesn’t show up when we test our site though.
UPDATE: Apparently, this seems to be fixed already by Google, so it’s no longer showing 0 seconds.
It is safe to say that our experiment by adopting our AMP + PWA strategy, and then modifying it a little to use other tech stack has resulted in a huge improvement to our homepage load speed. We have never used SvelteJS before this experiment, but we are very impressed by how small the bundle size can be. During our development we could not find a reliable linting and formatting tools for Svelte components. We do hope this situation will be improved in the future.
Coming from React ecosystem, we were hoping to find a de-facto routing library for Svelte, but no such library exists. On Svelte’s own awesome list there are 3 routing library listed, one isn’t Svelte-specific, and the others aren’t particularly regularly maintained.
We also would like to see something like react-loadable along with SSR support for Svelte. Currently lazyloading chunk on client side can be achieved with dynamic imports. But, lazyloaded chunks could not be rendered on server side. Currently, `react-loadable` achieves SSR support with `Loadable.preloadAll()`.
Well, it seems like SvelteJS version 3 is in the works, and we would probably be looking into it when it is released and hope that it will bring more good stuffs to the table!