Static assets get no configurable headers on native Cloudflare deploys of framework apps

オープン
#647 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

@dvkam がすでに取り組んでいます。

2026年11月2日 から。

  • #670 @dvkam による — オープン

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
50/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
活発
技術スタック
typescript, vite
領域
cloud

調査の方向性

Start by tracing uploadAssets, readGeneratedAssetHeaders, and planAssetWorkerBypass for native Cloudflare deploys, then compare their behavior with the TanStack Start asset configuration described here. Check or add coverage for user-authored _headers and fingerprinted assets; done means the reported cache headers are applied to static assets, or the docs accurately describe the limitation.

索引モデルが issue の本文から書いたものです。

説明

Summary

A TanStack Start app deployed with void deploy --platform cloudflare serves its static assets without any configurable headers:

  1. A public/_headers file is copied to dist/client/_headers, but it never applies in production. uploadAssets ignores /_headers, and readGeneratedAssetHeaders only sends a file whose first line is Void's generated marker ("A user-authored _headers is not sent on this path").
  2. Void's own immutable caching for fingerprinted bundles never runs either. planAssetWorkerBypass only applies when the built wrangler.json has assets.run_worker_first: ["/**"], and the TanStack Start build has only "assets": { "directory": "../client" }. With the _headers file removed, the build generates no _headers at all.
  3. As a result, hashed files under /assets/ are served with Cloudflare's default Cache-Control: public, max-age=0, must-revalidate. Browsers revalidate every JS and CSS chunk on every page view.

This contradicts two docs pages:

  • guide/edge/static-assets.md ("Native Cloudflare deployments"): "With void deploy --platform cloudflare, generated JavaScript bundles with content fingerprints receive immutable caching."
  • guide/edge/headers.md ("Framework _headers files"): "Void reads _headers files produced by supported frameworks."

Reproduction

  • [email protected], @tanstack/[email protected], Vite 8, deployed with void deploy --platform cloudflare
  • void.config.ts sets cloudflare.cache.enabled, a custom domain route, a D1 binding and no routing options
  • public/_headers:
    /assets/*
      Cache-Control: public, max-age=31536000, immutable
    
  • After deploy, curl -sI https://<site>/assets/<hashed>.js shows cache-control: public, max-age=0, must-revalidate. CSS is the same.

I also tried routing.headers in void.config.ts ('/assets/*': ['Cache-Control: public, max-age=31536000, immutable']). In the local preview (vite preview in workerd), assets still came back with max-age=0, must-revalidate. I didn't deploy that variant, since the assets are served without starting the Worker, so I don't expect the rules to reach them.

Expected

One of these, for framework apps on native Cloudflare deploys:

  • send a user-authored _headers with the asset upload (as Wrangler does),
  • generate the immutable _headers for fingerprinted files even without run_worker_first, or
  • apply routing.headers to static assets.

Failing those, the docs should say framework apps on --platform cloudflare get no asset headers.

Workaround

A Response Header Transform Rule on the zone that sets Cache-Control: public, max-age=31536000, immutable for a 200 under /assets/.

主要言語
TypeScript
スター
627
フォーク
66
平均マージ
13時間 57分
マージ済み PR(30日)
194

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

voidzero-dev/void のほかの issue

voidzero-dev/void の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。