Understanding the Page Caching Problem in Framework7

What Happens?

  • Pages show outdated content after returning via back navigation
  • PageInit and PageBeforeIn handlers do not fire on cached views
  • Data-bound templates render with stale values or empty content
  • Duplicate page elements appear in DOM after repeated routing

Why It Matters

In real-world apps with user input, live data, or authentication logic, stale pages create functional inconsistencies, frustrate users, and break critical flows like checkout, forms, or onboarding. When unmanaged, they also leak memory and break navigation history.

Framework7 Routing Architecture

Page Lifecycle Events

Each page in Framework7 triggers lifecycle events like pageInit, pageBeforeIn, pageAfterOut, and pageBeforeRemove. These are central to triggering data loading, DOM manipulation, and cleanup logic.

Router Caching

By default, Framework7 caches pages to speed up navigation. This means route changes may return to a pre-rendered page instance, skipping full reinitialization and bypassing data refresh logic unless manually handled.

Root Causes

1. Caching Enabled Without Conditional Refresh

If keepAlive or cache is enabled without invalidation logic, cached pages won't re-run setup code, leading to data staleness.

2. Missing or Misplaced Lifecycle Hooks

Placing API calls or DOM updates only in pageInit instead of pageBeforeIn causes one-time execution and stale UIs on subsequent entries.

3. Inline Pages and Named Routes Conflict

Using the same route path with inline pages and named page components can cause duplication or improper caching due to conflicting DOM injection behavior.

4. Asynchronous Data Loads Out of Sync

When async data populates after page render, the UI may not update unless explicitly redrawn, especially in cached views or when reused via tabs or popup routing.

Diagnostics

1. Enable Router Debug Logs

Set router: { log: true } in the Framework7 app init config to observe routing decisions, cache hits, and view stack behavior.

2. Log Lifecycle Events Per Page

on: {
  pageInit() { console.log('Init', this); },
  pageBeforeIn() { console.log('BeforeIn', this); },
  pageAfterOut() { console.log('AfterOut', this); },
}

Ensure expected events fire in every navigation scenario. Missing logs often indicate cached page reuse.

3. Inspect DOM for Orphaned Pages

Use browser dev tools to examine .page elements inside the view. Repeated navigation should not leave behind stale or duplicated pages.

Step-by-Step Fixes

1. Use pageBeforeIn for Data Reload

Place dynamic data refresh logic in pageBeforeIn instead of pageInit to ensure execution every time the page becomes visible.

2. Disable Cache for Volatile Pages

routes: [{
  path: '/profile/',
  url: './pages/profile.html',
  options: { cache: false }
}]

Prevent Framework7 from reusing outdated content for user-specific or time-sensitive pages.

3. Manually Clear Page Cache on Logout or Refresh

Use router.clearPreviousHistory() or router.clearCache() when switching user contexts or re-authenticating.

4. Use Unique Page Keys for Dynamic Pages

When rendering the same route with different data, append a unique parameter or query string to force a new page instance.

5. Watch and Bind Asynchronous State Changes

If using Vue or React, ensure state updates trigger reactivity in templates using watchers, computed properties, or force updates when reusing components.

Best Practices

  • Minimize use of cache: true on pages with volatile data
  • Always use pageBeforeIn for updates that must occur on every view
  • Regularly audit the DOM for stale views in app views
  • Isolate route-level logic from shared component state to avoid desync
  • Use route parameters to distinguish reusable components with different contexts

Conclusion

Navigation and caching inconsistencies in Framework7 arise from a mismatch between internal router logic and developer expectations around lifecycle behavior. By mastering the page lifecycle, controlling cache behavior, and carefully managing data reactivity, developers can build smooth, robust mobile applications. In high-complexity apps, reliable view management is essential to ensuring a seamless user experience and application correctness.

FAQs

1. Why doesn't my data update when returning to a page?

Because Framework7 may reuse the cached version. Move your data refresh code to the pageBeforeIn event instead of pageInit.

2. Can I force a full reload of a page?

Yes. Use router.navigate('/path/', { reloadCurrent: true }) to re-render and re-run page logic from scratch.

3. What's the difference between pageInit and pageBeforeIn?

pageInit runs only once per page instance. pageBeforeIn runs every time the page becomes visible—even if cached.

4. How do I clean up memory from old pages?

Use pageBeforeRemove to destroy timers, listeners, or DOM elements. Also call router.clearCache() if necessary.

5. Are inline pages more reliable than external templates?

Not necessarily. Inline pages are faster but harder to maintain in modular apps. External templates provide better separation and caching control.