Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cache-busting page-data.json files in Gatsby

I have a gatsby generated website on which I have replaced the contents of the homepage.

Unfortunately the previous version was serving up /page-data/index/page-data.json with the incorrect cache-control headers, resulting in /page-data/index/page-data.json being cached on client browsers (and stale data being shown unless force-refreshed). I have also discovered that page-data.json files are not hashed (see https://github.com/gatsbyjs/gatsby/issues/15080).

I've updated the cache-control headers so that versions from now on will not be cached but this does not help with clients that have the cached version now.

What can I do to force clients to request the latest version of this file?

like image 731
millarnui Avatar asked Oct 03 '19 16:10

millarnui


People also ask

How do I clear my Gatsby cache?

Clearing cache Since cache files are stored within the . cache directory, deleting it will clear all cache. You can also use gatsby clean to delete the . cache and public folders.

Can HTML be cached?

Implementing user personalization in scripts allows caching of the page's HTML. Then the scripts can modify the page after loading asynchronously. Beyond using JavaScript for personalization, The Gap is caching HTML.


1 Answers

I got there in the end... This is in my gatsby-node.js

const hash = md5(`${new Date().getTime()}`)

const addPageDataVersion = async file => {
  const stats = await util.promisify(fs.stat)(file)
  if (stats.isFile()) {
    console.log(`Adding version to page-data.json in ${file}..`)
    let content = await util.promisify(fs.readFile)(file, 'utf8')
    const result = content.replace(
      /page-data.json(\?v=[a-f0-9]{32})?/g,
      `page-data.json?v=${hash}`
    )
    await util.promisify(fs.writeFile)(file, result, 'utf8')
  }
}

exports.onPostBootstrap = async () => {
  const loader = path.join(__dirname, 'node_modules/gatsby/cache-dir/loader.js')
  await addPageDataVersion(loader)
}

exports.onPostBuild = async () => {
  const publicPath = path.join(__dirname, 'public')
  const htmlAndJSFiles = glob.sync(`${publicPath}/**/*.{html,js}`)
  for (let file of htmlAndJSFiles) {
    await addPageDataVersion(file)
  }
}
like image 162
millarnui Avatar answered Sep 16 '22 15:09

millarnui