I think a combination of related resource links and next links is a very good fit here - unless I was wrong with my assumption that this is about empress-blog.
The tag resource references the related posts, through a related resource link. This related resource link points to the first page of the resources for that tag. Something like this:
{
"type": "tags",
"id": "1",
"relationships": {
"articles": {
"links": {
"related": "/tags/1/posts-1.json"
}
}
}
}
The related resource link returns the resource documents for the first 5 articles in default sorting order. Additionally it has a next
link as described in pagination chapter of JSON:API spec. If there are more than 5 articles for that tag, the links.next
points to the second page. If there aren’t more articles for that tag, it’s null
. As the first page does not have any previous page links.prev
is null
. It would look like this:
{
"data": [
// resource objects of first five articles for that tag
],
"links": {
"next": "/tags/1/posts-2.json",
"prev": null
}
}
The second page would then contain the link to the third one or null
if there aren’t more articles for that tag. Additionally it would have a links.prev
pointing to the first page. You may additionally add links.first
and links.last
if you want to provide that functionality.
The same logic could be used to serve paginated articles by author.
There are a few drawbacks to note compared with the current architecture:
- The logic to generate the static JSON files at build-time gets more complex.
- The bundle, which needs to be hosted, gets bigger as the same article would be included in many JSON files (it’s main location + one time per tag used on it).
- A user may need to download the same article multiple times depending on the usage. This gets as more likely as more different views on the content (e.g. main blog, different tags, different authors).
If you are worried about bundle size or expect a regular user to open multiple views, you could consider using relationship links. While a related resource link must return with a list of resource objects on a GET
request, the relationship link returns a list of resource identifier objects. A resource identifier object only contains id
and type
but not the fields (attributes
and relationships
). So the payload of a relationship link is way smaller than the one of a related resource link.
It comes with the main drawback that you need multiple requests to fetch the related resources unless they are already in client-side cache: One to get a list of related resources and then one for each related resource to get the actual content. At the end of the day it’s a trade-off between initial render time and less overfetching on intensive usage.
For your specific use case cacheability might also be important. You could fingerprint the articles by using a hash of their content as ID. If serving them as individual files and using their ID as a file name, they could be cached forever thanks to fingerprinting. On deployments invalidating the lightweight relationship links would be enough. To be honest I’m not sure how that would fit with the main page without adding a needless resource just to serve the list of articles used on it through a relationship link.
Disclaimer: Haven’t used relationship links and pagination links in Ember Data for a while. Not sure how well they are supported. But maybe Ember Data would not be needed at all for this simple use case? A service, which fetches the articles and implements a client-side cache might be enough. The rest seems to be lightweight enough that overfetching should not matter that much.