Introduction
Caching is the technique of storing resources and serving them back when requested. When a similar request is made for the second time, cached resources are served instead of fetching resources from server. Cached data are snapshots of the requested resource that expires after a given time. The advantage of caching is that it liberates the server from preforming unnecessary tasks while improving response time.
There are several types of caches these are grouped into two main categories. private or shared caches.
- Shared cache: The cache is stored for reuse by more than one user.
- Private cache: The cache is dedicated to a single user.
Real world examples and caching benefits
Lets say for example you visit chekiprice search for “mini pc”. The request is processed by our servers through crawling a couple of stores on the internet. The API then responds back with a bunch of mini pc in Kenya (data includes their prices and stores URLs) but before responding the API does caching for the expensive operation. When the next user located somewhere else makes the same request to the API for “mini pc”. The server responds immediately from cached data and does not crawl stores on the internet. This is what we call shared cache, the cache is shared amongst users. Of courses the cache expires after some time. Otherwise we would serve invalid data.
This is good but not enough to make user web experience seamless.
Now imagine after getting the response from the API the data is rendered to the browser. The user is unsatisfied with the results, edits his/her search to search for “intel mini pc”. The user then decides to go back.
The browser recreates the components all over again and make the API call all over again. However this is an unnecessary request and unnecessary recreating of the components since the data is unchanged. Its always a good idea to minimize the amount of API calls. Not only does minimizing API calls save time but also server resources.
This inefficiency leads to the need for browser caching. This type of caching would immensely reduce API fetch times and components rendering for already rendered components. The cache is privately held and not shared amongst users. This technique of caching is a form of private cache.
API caching
Depending on what language your API written in you can attempt to do the caching by yourself or check if there is an existing plugin for caching. If your option is creating the API by yourself I would recommend using REDIS for caching. However if your using flask there is a great plugin known as Flask-Caching for caching requests. It’s very easy to get started.
Simple flask caching with flask-caching
Installation
pip install Flask-Caching
Sample Code
from flask import Flask
from flask_caching import Cache
config = {
"DEBUG": True, # some Flask specific configs
"CACHE_TYPE": "simple", # Flask-Caching related configs
"CACHE_DEFAULT_TIMEOUT": 300
}
app = Flask(__name__)
# tell Flask to use the above defined config
app.config.from_mapping(config)
cache = Cache(app)
@app.route("/")
@cache.cached(timeout=10) #cache for 10 seconds
def index():
random_number = randint(1,100) #generate random number
return f'Random number: {random_number}'
#run app
if __name__ == '__main__':
app.run()
Expected behavior: The random number is cached for 10 seconds. When you reload the page before 10 seconds elapse data is fetched from the cache. The random number generator doesn't get executed until 10 seconds are up. In real word this could be an expensive operation.
VUEJS CACHING
Keep-Alive
The keep-alive tag in Vuejs is used for caching component instances once created. This is to avoid re-rendering the component every time. Depending on your use case keep alive can be an advantage or a disadvantage.
Disadvantages of keep alive
- The use of keep-alive means you lose access lifecycle hooks i.e created, mounted.
- If rely on building and destroying components you should probably keep away.
Advantage of keep-alive
- Quicker user switching between pages
- Components make API call only once
- Enable ease in storing the scroll position
- Useful for caching form data.
Keep-alive hooks
To observe switching between cache keep-alive has two unique lifecycle hooks.
- activated : Called when a kept alive component is activated.
- deactivated: Called when, you guessed it, a kept alive component is deactivated.
How the keep-alive hooks look like in action:
mounted() {
console.log('Called when have mount')
},
activated () {
console.log('Called when have activated')
},
deactivated () {
console.log('Called when have deactivated')
}
Caching Vuejs routes and keeping scroll position.
In order to cache routes we enclose <router-view></router-view> with keep-alive. We’ll use vue-keep-scroll-position package to assist in remembering the scroll position.
Install vue-keep-scroll-position
npm i -S vue-keep-scroll-position
Add package to Main.js
import Vue from 'vue'
import VueKeepScrollPosition from 'vue-keep-scroll-position'
Vue.use(VueKeepScrollPosition)
Add code for caching routes in App.vue
Assumption: Your using vue router
<keep-alive>
<router-view v-keep-scroll-position></router-view>
</keep-alive>
And just like that you have implement remembering scroll position and caching on your Vue application.
(Advanced) Caching Vuejs routes and Remember scroll position without a third party package.
You don't need a third party package for vue to recall scroll position. In order to cache routes we just enclose the router- view with keep-alive, this time we dont add v-keep-scroll-position prop.
<keep-alive>
<router-view></router-view>
</keep-alive>
Remember Vuejs scroll position without third party package.
In order to remember scroll position add the following code in main.js after defining router.
const router = new VueRouter({
mode: 'history',
routes
}) //defining router
const scrollableElementId = 'content' // You should change this
const scrollPositions = Object.create(null)
router.beforeEach((to, from, next) => {
let element = document.getElementById(scrollableElementId)
if (element !== null) {
scrollPositions[from.name] = element.scrollTop
}
next()
})
window.addEventListener('popstate', () => {
let currentRouteName = router.history.current.name
let element = document.getElementById(scrollableElementId)
if (element !== null && currentRouteName in scrollPositions) {
setTimeout(() => element.scrollTop = scrollPositions[currentRouteName], 50)
}
})
And that's it.