Long term caching of endpoints is designed for static sites or server side rendered sites that use a moderate number of data entries, eg. blog posts, products, services, showcases, etc…
It is enabled using config.hash. When true, the endpoints JSON files will be created using a content based hash in their name.
It will also generate a manifest.json file to load on first page load, like a Webpack manifest. It contains a hash tree that maps each endpoint's name to its hash. However its size should be watched a lot more closely as there might be a lot more API entries than JS/CSS/… files to load with Webpack.
When rendering server side, the manifest must be either:
-
required orimported and inlined as a global variable (eg.window.__API__) in the HTML response, and then eventually handled by a state management library (Redux, MobX, Angular, etc…) and cached client side usingsessionStorage,localStorage, orAppCache -
imported in a dedicatedservice/api.jsmodule, which must be loaded itself by the client app either on page load or on demand, ie. usingimportorimport(), bundled with other JS entries or with async (normal) chunks
Example using Redux:
const { list, page, slug } = requestArgs
const { categories, entities, indexes } = reduxStore.getState().apiManifest
const categories = fetch(categories).then(response => response.json())
const entities = fetch(indexes[list][page]).then(response => response.json())
const entity = fetch(entities[slug]).then(response => response.json())Example using service/api.js (static import):
import api from './manifest.json' // Generated by markdown-api
/**
* get :: Query -> FetchInit -> Promise Error Response
*
* Query => { type: EntityType, slug?: EntitySlug, list?: IndexName, page?: Number }
*/
const get = (query, initFetch) => {
let path
if (query.type === 'categories') {
path = `${api['categories']}`
} else if (query.list) {
path = `${api[type].indexes[list][page]}`
} else if (query.slug) {
path = `${api[type].entities[slug]}`
} else if (!path) {
throw Error('Unable to construct API path to fetch')
}
return fetch(path, initFetch).then(response => reponse.json())
}If config.hash and config.subVersion are both true, stale endpoints will not be removed. This feature might be used to diff between updates, like in a Github repository.
Note: you can also version control only source files, host them on Github, fetch diffs using its API, and render source/processed content client side.