How Bilibili Scaled Its Frontend: From MVC to Vue SSR and Koa

This article chronicles Bilibili’s front‑end evolution in 2017, detailing the shift from a backend‑centric MVC model to front‑back separation, the adoption of Node middle‑layers, Vue and React SSR, Docker deployment, caching strategies, and subsequent refactoring to improve performance and scalability.

Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
How Bilibili Scaled Its Frontend: From MVC to Vue SSR and Koa

Bilibili’s Frontend Journey

In 2017 Bilibili transitioned from a backend‑centric MVC architecture to a front‑back separation model to reduce coupling and communication overhead.

Front‑Back Separation Modes

Two basic patterns were explored: a simple static‑HTML approach without a middle layer, and a Node‑based middle layer introduced in 2009 that enabled JavaScript to run on the server.

The static approach serves an HTML template with linked JS/CSS, fetching data via AJAX. The Node middle‑layer approach bundles assets with Webpack, uploads them to a CDN, and serves the HTML from a static server while the backend provides APIs.

SSR Challenges and Solutions

Initial SSR using Vue on the server caused first‑paint white‑screen issues and poor SEO for SPA pages, prompting a shift to server‑side rendering for SEO‑critical pages.

Framework Selection

Node frameworks considered were Hapi, Express, and Koa, with Egg.js rejected for being heavyweight and opaque. Express was initially chosen for its simplicity, later replaced by Koa2 for better async/await support and middleware flow.

Front‑end frameworks Vue and React were selected for their ability to support isomorphic rendering.

Project Structure

Key directories:

client – front‑end (Vue) code and Webpack build logic

server – back‑end code (Express/Koa) with MVC‑like structure

build, config, dist, package.json, etc.

Server‑Side Rendering Implementation

Vue SSR was built using

const { createBundleRenderer } = require('vue-server-renderer')

and const renderer = createBundleRenderer(serverBundle, {... }). Two entry points were defined: entry-client.js for the browser bundle and entry-server.js for the server bundle.

Deployment and Caching

The service was containerized with Docker (1 CPU, 4 GB RAM) across two instances, later scaled to six. Caching was added at both CDN and file‑system levels to handle up to 10 million daily visits.

Configuration center integration allowed dynamic versioning of front‑end bundles without restarting services.

Refactoring and Automation

Core libraries were extracted into an internal npm package, enabling other teams to reuse the SSR infrastructure. Scaffolding tools were created to generate projects with pre‑configured Webpack and package.json files.

Performance Testing

Stress tests revealed CPU bottlenecks on 1C4G servers, especially with Vue 2.3.x. Upgrading to Vue 2.4.x and adding component/page caches improved throughput, though CPU remained the limiting factor.

Conclusion

The migration from static pages to a full SSR architecture required close collaboration between front‑end and back‑end teams, iterative framework selection, and robust deployment pipelines. Ongoing challenges include memory leaks and performance tuning, but the overall front‑end performance and scalability have markedly improved.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

frontendDockerNode.jsSSRVueKoa
Tencent IMWeb Frontend Team
Written by

Tencent IMWeb Frontend Team

IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.