Vue Storefront 2 Composables Keep UI Decoupled From Commerce Backends
Vue Storefront 2 replaces a monolithic store with granular composables like useCart and useProduct. The pattern decouples UI from commerce backends via a middleware layer, enables SSR prefetching and typed state, with trade-offs around over-fetching and middleware scaling.
25 Jul 2025, 05:50 UTC

Moving a storefront between commerce platforms usually means rewriting data fetching, state handling, and error normalization across dozens of components. Vue Storefront 2.x makes that problem explicit by replacing a monolithic store with granular composables like useCart, useProduct and useUser. The thesis is simple: keep UI logic in small, typed composables and push platform specifics into a middleware layer. Components stay stable when the backend changes.
What a composable actually returns
Each domain composable encapsulates one concern and exposes a predictable shape: reactive state, actions, and computed getters. That consistency lets you consume cart, product or user data the same way in pages, components and middleware.
A typical contract looks like state for current data, methods such as load, add or update, and derived values. Because the composables are built on Nuxt 3 primitives, they are tree-shakable and testable in isolation. You can replace a Vuex module behind the same interface during migration and swap the implementation later without touching consumers.
Backend agnostic via middleware
The composables do not call Commerce Tools, Shopify, BigCommerce or Adobe Commerce directly. They call a local middleware API. The middleware implements a unified contract and translates requests to the active platform adapter.
This separation is the engineering decision that enables multi-backend support. Frontend code stays platform neutral; only the middleware api-client directory changes when you add a new integration. For custom backends you must implement the full contract: unified methods, normalized errors and context passing. That work is non-trivial for niche platforms.
SSR, typing and incremental adoption
Composable signatures are designed to work with Nuxt 3 useAsyncData. During SSR the composable prefetches data, the payload is serialized into __NUXT_DATA__, and the client hydrates without duplicate requests. That avoids waterfall fetching on first paint.
TypeScript inference is first class. Schemas are code-generated from GraphQL, so state and method signatures are typed. IDE autocomplete improves and many runtime mismatches surface at build time.
Incremental adoption is practical. Legacy Vuex modules can be wrapped behind a composable facade, then replaced piece by piece.
Worked example: cart mini widget
Create a project to inspect the pattern:
npx @vue-storefront/cli create my-storeRun the command in a terminal with Node 18+ and write permission in the target directory. The scaffold creates src/composables/ with useCart, useProduct, useUser etc. Inspect those files to see the state, methods and getters contract.
Start the dev server:
cd my-store
npm run devOpen the project in an editor and add a small component that consumes the cart composable. A minimal usage pattern is:
// components/CartMini.vue
import { useCart } from '#imports'
export default {
setup() {
const { cart, loading, addItem, load } = useCart()
// load is typically called in page setup or via middleware prefetch
return { cart, loading, addItem }
}
}Check the network tab in devtools. You should see requests going to the local middleware path, not directly to the commerce API. In SSR mode, inspect the HTML source for __NUXT_DATA__ to verify prefetch payloads are present. Review node_modules/@vue-storefront/*/dist/index.d.ts to confirm typed signatures are exported.
Risks: changing composable signatures between minor versions has happened in the 2.x line. Pin dependencies and review changelogs before upgrades. Middleware is a critical scaling point; latency, caching and observability there directly affect frontend performance.
Trade-off: granularity vs over-fetching
Fine-grained composables improve reuse but can cause over-fetching when a page uses several composables independently. Each call may trigger its own middleware request. For list pages consider batching with a custom composable or useFactory to coalesce queries. Monitor the middleware logs for duplicate requests per navigation.
A practical check is to render a product listing page and count middleware calls in devtools. If multiple composables fire separately for the same entity, consolidate them.
Actionable closing
Audit which composables your pages use and whether they are consumed through a single entry point. Pin @vue-storefront/* versions, add middleware observability for latency and error rates, and batch requests where granularity creates extra round trips. Keep UI components dependent only on the composable contract, not on a specific commerce platform.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.