Frontend Development 20 min read

Bifrost: Meituan’s Vue‑Based Micro‑Frontend Framework for Scalable Enterprise Front‑End Development

The article introduces Bifrost, Meituan’s Vue‑based micro‑frontend framework, detailing its background, design goals, architecture, implementation code, development practices, deployment workflow, and the benefits and challenges of adopting micro‑frontend architecture in large‑scale enterprise front‑end projects.

Qunar Tech Salon
Qunar Tech Salon
Qunar Tech Salon
Bifrost: Meituan’s Vue‑Based Micro‑Frontend Framework for Scalable Enterprise Front‑End Development

Meituan’s Flash‑Buy team built a micro‑frontend framework called Bifrost to address the growing complexity of a single‑page application that evolved into a multi‑tenant management platform. The article shares the motivation, design decisions, core architecture, implementation details, and practical lessons learned.

Project Background

The original "Enterprise Management Platform" was a Vue SPA for a single merchant. As the product expanded to serve many merchants, multiple front‑end teams began to encounter code conflicts, divergent customizations, and the need to integrate existing features.

Solution Selection

Key requirements were independent development and deployment of modules, low‑cost integration of existing projects, isolated runtime, SPA experience, and Vue‑centric compatibility. After evaluating Nginx routing, iframe embedding, internal HR‑system micro‑frontend, and SingleSPA, the team chose to develop a custom solution.

Core Architecture

Bifrost follows the SingleSPA idea and splits the system into a host (main) application and multiple child applications.

Host responsibilities: maintain a registry of child apps, manage their lifecycles, dispatch routing, load entry resources, and provide mount points.

Child apps focus on business logic; they can be business, menu, or layout subsystems, with the layout subsystem loading before business subsystems.

Routing messages are broadcast on a bus; when the route changes, the appropriate child app is loaded or the current app handles the route.

Specific Implementation

Main System

The host creates a Platform instance and registers child apps with appName , optional domain , and configPath pointing to a JSONP configuration file.

import { Platform } from '@sfe/bifrost'
new Platform({
  layoutFrame: { render() { /* render layout */ } },
  appRegister: [{ appName: 'app1', configPath: '/path/to/app1/config.js' }]
}).start()

Business Subsystem

Business apps are wrapped in an AppContainer . The container mounts a Vue instance inside its mounted hook, keeping the original code untouched.

import { AppContainer } from '@sfe/bifrost'
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const router = new VueRouter({})
new AppContainer({
  appName: 'app1',
  router,
  mounted() {
    return new Vue({ router, components: { App }, template: '
' }).$mount()
  }
}).start()

Layout Subsystem

The layout uses LayoutContainer instead of AppContainer . It renders the navigation menu and can be shipped as an NPM package or a static asset.

import { LayoutContainer } from '@sfe/bifrost'
import Vue from 'vue'
import App from './app'
new LayoutContainer({
  appName: 'layout',
  router,
  onInit({ appSlot, callback }) {
    Vue.config.productionTip = false
    const app = new Vue({ el: '#app', router, store, render: h => h(App, { props: { appSlot } }) })
    callback()
  }
}).start()

Engineering Practice

Local Integration

During development, MockPlatform simulates the host by loading child apps from their production URLs, providing a seamless local development experience.

new AppContainer({
  runDevPlatform: process.env.NODE_ENV === 'development',
  devPlatformConfig: {
    layoutFrame: { mode: 'remote', configPath: 'path/to/layout/config.js' },
    appRegister: [{ appName: 'app2', mode: 'remote', configPath: 'path/to/app2/config.js' }]
  }
}).start()

Global State

All child apps share a Vuex store maintained by the host. Apps subscribe to the global store via syncGlobalStore , which mirrors changes into a local Global namespace.

import { AppContainer, syncGlobalStore } from '@sfe/bifrost'
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({})
new AppContainer({
  mounted() {
    syncGlobalStore(store)
    return new Vue({ store, router, components: { App }, template: '
' }).$mount()
  }
}).start()

Common Dependencies

Webpack externals are used to exclude shared libraries (lodash, moment, etc.) from child bundles. The host builds a DLL containing these dependencies, while Vue itself remains in each child to avoid prototype conflicts.

Module Reuse

Shared UI components and utility libraries are kept in separate Git repositories and linked into the host via Lerna and Git submodules, enabling version‑controlled reuse across all child apps.

Release & Deployment

Child app configurations are loaded via JSONP; publishing merely uploads static assets to CDN. Meituan’s internal CI platform Talos handles static resource deployment.

Version Control & Gray Release

The host queries a version service to determine whether a user belongs to the full‑traffic or gray‑traffic lane, then loads the appropriate child app versions. This enables incremental upgrades and controlled roll‑outs.

Tracking & Error Reporting

Hooks such as onAppLoading , onAppLoaded , onAppRouting , and onError allow the host to record PV, loading success rates, and error details for each child app.

Benefits

Complete decoupling of remote teams eliminates code‑merge conflicts.

Micro‑frontend boundaries prevent the SPA from becoming a monolithic “big‑rock” application; each child stays under ~30 pages.

Component library upgrades can be performed incrementally, reducing downtime and risk.

Not a Silver Bullet

Micro‑frontend introduces extra complexity: multiple repositories, unified coding standards, automated release pipelines, and cross‑domain cookie handling. Teams should evaluate whether the benefits outweigh the overhead before adopting.

When to Consider Micro‑Frontend

Large back‑office systems with many relatively independent functional modules.

Projects with substantial legacy code where new features need to be added without rewriting the whole application.

Future Directions

Planned improvements include richer front‑end micro‑service governance tools, JavaScript/CSS sandboxing, and support for additional technology stacks.

Conclusion

Micro‑frontend architecture addresses the growing complexity of modern front‑ends. By sharing the Flash‑Buy team’s year‑long experience with Bifrost, the article aims to provide a concrete, production‑grade reference for engineers exploring similar solutions.

Author

Yu Fu, Front‑End Engineer at Meituan Flash‑Buy.

state managementmicro-frontendmodule federationVuefrontend architectureWeb DevelopmentBifrost
Qunar Tech Salon
Written by

Qunar Tech Salon

Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.

0 followers
Reader feedback

How this landed with the community

login 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.