I have a Nuxt 3 app that hits a rest API in order to display a paginated list of blog previews. Each preview can be tapped on to view the entire blog.
My app interfaces with 2 API endpoints.
GET /api/v1/blogs
returns a paginated listing of blogs.GET /api/v1/blog/:slug
returns a single blog by an identifier.
Make as few server/API requests as possible, since much of the data can be easily cached on the client-side.
- If I load the first page of blogs and then navigate to page 2, it should load the second page of blogs on the client-side. If I navigate back to page 1, the client-side application should attempt to re-use the data that was previously fetched.
- If I tap on an individual blog from this listing, I should navigate to the individual blog page, but the app should not have to make an API request since the blog I'm tapping on was already loaded with the listing.
- Landing on any blog page, whether it be a listing or an individual blog, should make a server side API request to fetch the relevant data, display it, and cache it.
- Use as much built-in functionality as possible.
- Don't duplicate data in the cache.
I'm attempting to solve this with composables - useNuxtApp
, useLazyFetch
and the built in getCachedData()
hook.
Goal #1 is easily solved with getCachedData()
, the useNuxtApp().payload.data
object, and a cache key
that is specific to the relevant page/querystring.
#2 is a little trickier. To reuse the useNuxtApp().payload.data
cache from the blog listing, I need to know the key that the individual blog lives within. To solve this, I'm writing the most recent listing's complex key
into a custom pinia store with a more obvious key (e.g. mostRecentBlogs = blogs?page=23
). Then, on the individual blog page, I can ask pinia for the key of the most recent blog listing, get its data, and see if my blog is in there via js array filtering. If it exists, return it instead of making an API request.
The rest feels solved and/or close.
I'm just looking for thoughts on this approach. It solves the issue and seems incredibly performant, but the code feels a little more heavy handed than it needs to be.
Example files below 👇