PostHog / posthog-js

Send usage data from your web app or site to PostHog, with autocapture.
https://posthog.com/docs/libraries/js
Other
303 stars 126 forks source link

Always invalidating cache using fetch in NextJs #1529

Open maiconsanson opened 1 week ago

maiconsanson commented 1 week ago

Bug Description

After enabling fetch logs in the next.config, I noticed that the cached result from API calls using the extended native fetch is always invalidated with the message: Cache skipped reason: (cache-control: no-cache (hard refresh)) when fetching any API endpoint from a page.

I'm using "next": "15.0.3" with the app folder and followed the PostHog documentation on using the client.

The result is always fresh when hitting the same endpoint multiple times:

Screenshot 2024-11-17 at 11 09 43

However, it should be the cached result:

Screenshot 2024-11-17 at 12 02 24

How to reproduce

  1. Enable the fetch logs in the next.config.
    const nextConfig = {
    logging: {
    fetches: {
      fullUrl: true,
    },
    },
    }
  2. Follow the app router docs (client version).
  3. Make a request from a page to an API endpoint using the native fetch (setting a cache time).

Additional context

  1. With the server-side configuration using the posthog-node package, the problem doesn't occur, but it's not possible to use session replays.
  2. The pages are server-side rendered, and I'm using the client provider to wrap them. Could that be the problem?
  3. My layout is a server component, so I can't import the PostHogPageView using dynamic with ssr: false as stated in the documentation:
    
    // Layout: without dynamic importing of PostHogPageView

import { PostHogClientProvider } from '@src/app/providers'

// irrelevant code

{children}
4. Even when importing the `PostHogPageView` dynamically inside the provider, the behavior remains the same:
```jsx
// Provider: with dynamic importing of PostHogPageView

'use client'

import { useEffect } from 'react'
import dynamic from 'next/dynamic'
import posthog from 'posthog-js'
import { PostHogProvider } from 'posthog-js/react'
const PostHogPageView = dynamic(() => import('@components/PostHogPageView'), {
  ssr: false,
})

const POSTHOG_KEY = process.env.NEXT_PUBLIC_POSTHOG_KEY
const POSTHOG_HOST = process.env.NEXT_PUBLIC_POSTHOG_HOST

export default function PostHogClientProvider({ children, isProduction }) {
  useEffect(() => {
    if (isProduction) {
      posthog.init(POSTHOG_KEY, {
        api_host: POSTHOG_HOST,
        person_profiles: 'identified_only', 
        capture_pageview: false,
        capture_pageleave: true,
      })
    }
  }, [])

  return isProduction ? (
    <PostHogProvider client={posthog}>
      <PostHogPageView />
      {children}
    </PostHogProvider>
  ) : (
    children
  )
}