From 1d8f188df451582cee570ed19d4924e10d86eb9f Mon Sep 17 00:00:00 2001 From: Leo Grosjean Date: Sat, 1 Aug 2026 23:14:40 +0200 Subject: [PATCH 1/2] fix: serve JavaScript assets with a stable MIME type --- reflex/utils/precompressed_staticfiles.py | 7 +++-- .../utils/test_precompressed_staticfiles.py | 29 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/reflex/utils/precompressed_staticfiles.py b/reflex/utils/precompressed_staticfiles.py index 16d78631d74..1c8cd690a67 100644 --- a/reflex/utils/precompressed_staticfiles.py +++ b/reflex/utils/precompressed_staticfiles.py @@ -143,7 +143,11 @@ def file_response( response_path: str | PathLike[str] = full_path response_stat = stat_result response_headers: dict[str, str] = {} - media_type: str | None = None + media_type = ( + "text/javascript" + if Path(full_path).suffix.lower() in {".js", ".mjs"} + else guess_type(os.fspath(full_path))[0] + ) if self._encodings: response_headers["Vary"] = "Accept-Encoding" @@ -151,7 +155,6 @@ def file_response( if sidecar is not None: content_encoding, response_path, response_stat = sidecar response_headers["Content-Encoding"] = content_encoding - media_type = guess_type(os.fspath(full_path))[0] or "text/plain" response = FileResponse( response_path, diff --git a/tests/units/utils/test_precompressed_staticfiles.py b/tests/units/utils/test_precompressed_staticfiles.py index dee29c22441..d7a7edaa007 100644 --- a/tests/units/utils/test_precompressed_staticfiles.py +++ b/tests/units/utils/test_precompressed_staticfiles.py @@ -121,6 +121,35 @@ async def test_precompressed_static_files_prefers_best_accept_encoding( assert await _collect_body(response, scope) == b"compressed-brotli" +@pytest.mark.asyncio +@pytest.mark.parametrize( + ("accept_encoding", "response_name"), + [("identity", "app.js"), ("gzip", "app.js.gz")], +) +async def test_precompressed_static_files_use_javascript_mime_independent_of_system_mapping( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, + accept_encoding: str, + response_name: str, +): + """Serve JavaScript with its standard MIME type despite a host override.""" + (tmp_path / "app.js").write_text("console.log('hello');") + (tmp_path / "app.js.gz").write_bytes(b"compressed-gzip") + monkeypatch.setattr( + "reflex.utils.precompressed_staticfiles.guess_type", + lambda _path: ("text/plain", None), + ) + + static_files = PrecompressedStaticFiles(directory=tmp_path, encodings=["gzip"]) + response = await static_files.get_response( + "app.js", _scope("/app.js", accept_encoding) + ) + + assert isinstance(response, FileResponse) + assert str(response.path).endswith(response_name) + assert response.media_type == "text/javascript" + + @pytest.mark.asyncio async def test_precompressed_static_files_fall_back_to_identity(tmp_path: Path): """Keep serving the original file when no accepted sidecar is available.""" From 0404cb783d9ee682d71e9f6da13012293dcd45f0 Mon Sep 17 00:00:00 2001 From: Leo Grosjean Date: Sat, 1 Aug 2026 23:20:30 +0200 Subject: [PATCH 2/2] chore: add changelog fragment for JavaScript MIME fix --- news/6831.bugfix.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/6831.bugfix.md diff --git a/news/6831.bugfix.md b/news/6831.bugfix.md new file mode 100644 index 00000000000..f0f95a89a6f --- /dev/null +++ b/news/6831.bugfix.md @@ -0,0 +1 @@ +Fix production frontend hydration on Windows when the system MIME registry maps JavaScript files to `text/plain`.