Our Team’s Journey with Vue 3 Composition API and Insights from ECS Architecture
The article recounts a frontend team's evolution from Vue 2 to Vue 3, detailing their experiments with the script‑setup syntax, challenges of maintainability, and how concepts from game‑engine ECS architecture inspired new composition‑API best practices for scalable, readable code.
0x00 The Birth of Vue 3
In 2022 our team adopted Vue 3 for a new internal project, discarding Webpack for Vite, Vuex for Pinia, and Vue 2 for Vue 3, and unanimously voted to use the new composition API.
0x01 script setup? Just That Simple
Following the official docs we started using <script setup> , finding the code much simpler than the options API because it feels like plain JavaScript rather than object‑oriented syntax.
We quickly appreciated the speed of writing with ref and reactive , although the initial learning curve was steep.
Use ref for declaring reactive variables.
Use shallowRef only when third‑party objects need reactivity.
Use reactive only when a composable requires a namespace.
0x02 Crisis: Product Manager Changes Business Logic
Without tests, frequent product‑manager driven changes forced us to edit dense component code full of const and function declarations, making the codebase feel like digging through a mess.
0x03 Back to Options API
Frustrated, the team reverted to the options API, noting its clearer structure and better team‑wide consistency.
0x04 Game Engine Inspiration: ECS Architecture
Observing the game Dyson Sphere Program , we learned that its Entity‑Component‑System (ECS) design stores similar data contiguously, enabling fast look‑ups.
ECS separates data (components) from behavior (systems), avoiding inheritance pitfalls.
0x05 Applying ECS Ideas to Vue
We realized that our misuse of composition API mirrored object‑oriented code; by grouping related logic together—just as ECS groups components—we could achieve clearer, more maintainable Vue files.
Using ref to replace data and regular functions to replace methods , we kept the same logical separation while staying within script‑setup.
// Example module pattern
/** @module XX1 – daily development */
const a = ref()
const b = computed()
onMounted(() => {})
function todoA() {}
/** @module XX2 – reusable */
const {c,d,todoC} = useXX2()
/** @module XX3 – namespaced */
const xx3 = reactive(useXX3())0x06 Guidelines Established
Logic Module Aggregation Principle : keep related code together.
Business‑First Principle : avoid over‑abstracting non‑reusable logic.
Core Module Retention Principle : keep frequently changed core logic inside the component.
These rules helped us quickly adapt a medical‑consultation feature from a web app to a mini‑program by sharing TypeScript modules across platforms.
0x07 Scaling Across Hospitals
By modularising business logic with composables, we could customize features per hospital (A, B, C, D) without duplicating entire codebases, using a macro‑compile step to include only the needed modules.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
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.