Bilibili’s Frontend Evolution: From MVC to Server‑Side Rendering with Vue and Node
This article chronicles Bilibili’s transition from a traditional MVC workflow to a modern front‑end/back‑end separation, detailing the adoption of Node middle‑layers, Vue SSR, architecture refactoring, deployment strategies, performance testing, and lessons learned throughout 2017.
In 2017 Bilibili reflected on its front‑end evolution, moving away from a backend‑centric MVC model where front‑end pages were delivered to the server for data binding, which caused high communication and integration costs.
Front‑end/Back‑end Separation was introduced to reduce coupling. Two patterns were described: a simple approach without a middle layer (static HTML served from a CDN, client‑side JavaScript fetching data via AJAX) and a Node‑based middle layer that enables richer interactions.
The first pattern was used for pages that did not require SEO, such as Bilibili history . After building with Webpack, the generated HTML, JS, and CSS were uploaded to a static server, while back‑end developers only needed to provide APIs.
The second pattern employed a Node middle layer. Initially Bilibili used Express, but later switched to Koa2 for better async/await support and onion‑style middleware, which simplified pre‑ and post‑processing of requests.
Choosing a Node framework involved evaluating Express, Koa, Hapi, and custom solutions like Egg.js. Express was selected at first for its simplicity, though it was eventually replaced by Koa2 during a refactor.
For the front‑end framework, Vue and React were considered; Vue was chosen because it supports universal (isomorphic) rendering, allowing the same logic to run on both client and server.
The project’s directory structure was organized as follows:
- client (isomorphic front‑end code) - server (Node back‑end, MVC‑style) - build, config, dist, etc.
Server‑side rendering was implemented using Vue SSR. The entry points entry-client.js and entry-server.js produced a client manifest and a server bundle, which were fed to the renderer:
const { createBundleRenderer } = require('vue-server-renderer'); const renderer = createBundleRenderer(serverBundle, { ... });
Configuration files mapped URLs to controllers, and a filter layer injected middleware before controller execution. Deployment used Docker containers (1 CPU / 4 GB) with two instances initially, later scaling to six instances thanks to caching layers.
Performance challenges included initial white‑screen delays, SEO issues with SPA rendering, and high CPU usage on 1C4G servers. To mitigate these, Bilibili added two‑layer caching (file‑based server cache and CDN cache) and later upgraded Vue from 2.3.x to 2.4.x, improving throughput.
A configuration center was introduced to manage bundle versions via hash identifiers, enabling hot updates without restarting services. This also allowed selective building of individual modules, reducing development latency.
Further refactoring extracted core utilities into an internal npm package, decoupling the front‑end library from the back‑end server and facilitating reuse across other departments.
Stress testing without caching revealed CPU saturation at ~100 % and limited TPS, highlighting the need for caching and efficient rendering strategies for high‑traffic pages.
In summary, the migration to front‑end/back‑end separation, Vue SSR, Docker deployment, caching, and a configuration‑driven workflow required close collaboration between front‑end and back‑end teams, iterative performance tuning, and continuous refactoring to sustain Bilibili’s rapid growth.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Architecture Digest
Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
