vercel / vercel/next.js

Docs: Unclear how to serve static assets generated during ISR

Open
#74,264 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
142k
Forks
32.4k
Avg merge
2d 14h
Merged PRs (30d)
351

Description

What is the documentation issue?

Looks like the topic "how to correctly serve static assets that were generated during ISR, how to save them, etc" is not quite covered in Next.js docs.

it's the only directory used to serve static assets but docs don't cover how to work with generated static assets... might be misleading.

Vercel Blob is probably the best way**, might need some more explanation in the docs, especially in conjunction with ISR, especially in regards to cleanup upon page invalidation.

Is there any context that might help us understand?

In my case I use Next.js ISR as facade for Notion DB. Per Notion's policy links to images will expire in 1 hour, but since page content can live much longer and won't be changed, it makes sense to cache it for longer than 1 hour, along with images. But same will be applied to any assets, that are not publicly hosted, and stored in some kind of expensive-to-fetch storage (bare S3 w/o Cloud Front included).

I searched Google but haven't found any definitive answer what's the best practice here...

Some considerations:

  • These images/assets may never expire, so they can be cached for way longer than page content
  • But they can be invalidated when page changes (but not always, only if they become unused, e.g. stop appearing on the page)
  • This ticket also raises more general concern, how to clean up things cached by route when route is invalidated
  • Trigger for cleanup could be both external event (Notion calling Route Handler when page is edited) or internal, when Next.js revalidates the stale page

Possible solutions (including some various trickery):

Vercel Blob is probably the best way, might need some more explanation in the docs.

  • put does not support supplemental metadata like keys to efficiently find and invalidate blobs
  • Purge Cache (Delete the entire contents of the Data Cache) won't affect blobs, so custom cleanup is needed

Upload these assets to an S3 bucket and serve via Cloud Front, with full control over deletion, expiration, etc.

  • Obvious drawback is that this requires a lot of coding and external service
  • Supports metadata

But what if no blob storage, just out of curiosity, or to adhere to "Next.js-only solution"?

Simply fetch these files with force-cache during build time, and use Route Handler to return cached result, since URL won't change until next build, we're good, but:

  • Route Handler is an overkill for static files both for cost and performance
  • Will bloat the cache if expiration will be set to months
  • Hard to invalidate manually upon incremental build, even with tags: revalidateTag is not allowed during render (Error: Route / used "revalidateTag xxx" during render which is unsupported. To ensure revalidation is performed consistently it must always happen outside of renders and cached functions.), and middleware.ts approach won't have access to ISR cache: Error: Invariant: static generation store missing in revalidateTag"
  • Feature request: It would be great if along with tags we could supply route to fetch calls, so that when route is revalidated, all subsequent fetches are revalidated also
  • Feature request: some simple callback like export const onRevalidate(params) { ... } to perform manual cleanup when page is revalidating
  • These two probably deserve another ticket, should I create one?

Save file to public folder

  • Can't set caching and middleware is not utilized during ISR
  • Will incremental build have access to previous artifacts (Only assets that are in the public directory at build time will be served by Next.js.), or will FS be properly merged between increments?

Break convention and fs.write files to .next/cache and then serve via Route Handler

  • Feels awkward
  • Will Purge Cache (Delete the entire contents of the Data Cache) clean everything?
  • Requires to use dynamic route to serve, which will cause extra load

Some links to prior similar issues & questions:

Does the docs page already exist? Please link to it.

https://nextjs.org/docs/app/building-your-application/optimizing/static-assets

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the static assets documentation page and review the linked ISR, Vercel Blob, prior discussions, and related questions. Determine whether the documentation should explain external storage, cache invalidation and cleanup, or separate feature requests; done means a scoped, definitive guidance update covering the supported approach.

Written by the indexing model from the issue text.

Assessment

Tech stack
nextjs
Domain
documentation
Issue type
Documentation
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
22/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.