diff --git a/.changeset/slow-socks-juggle.md b/.changeset/slow-socks-juggle.md
new file mode 100644
index 00000000000..8f7bc9cf626
--- /dev/null
+++ b/.changeset/slow-socks-juggle.md
@@ -0,0 +1,5 @@
+---
+"@remix-run/server-runtime": patch
+---
+
+Support 304 responses on document requests
diff --git a/integration/single-fetch-test.ts b/integration/single-fetch-test.ts
index 453ebe93db9..40a24fc0eb4 100644
--- a/integration/single-fetch-test.ts
+++ b/integration/single-fetch-test.ts
@@ -1925,8 +1925,23 @@ test.describe("single-fetch", () => {
`,
},
});
- let res = await fixture.requestSingleFetchData("/_root.data");
- expect(res.data).toEqual({
+
+ // Document requests
+ let documentRes = await fixture.requestDocument("/");
+ let html = await documentRes.text();
+ expect(html).toContain("
");
+ expect(html).toContain("Hello from the loader!
");
+ documentRes = await fixture.requestDocument("/", {
+ headers: {
+ "If-None-Match": "1234",
+ },
+ });
+ expect(documentRes.status).toBe(304);
+ expect(await documentRes.text()).toBe("");
+
+ // Data requests
+ let dataRes = await fixture.requestSingleFetchData("/_root.data");
+ expect(dataRes.data).toEqual({
root: {
data: {
message: "ROOT",
@@ -1938,13 +1953,13 @@ test.describe("single-fetch", () => {
},
},
});
- res = await fixture.requestSingleFetchData("/_root.data", {
+ dataRes = await fixture.requestSingleFetchData("/_root.data", {
headers: {
"If-None-Match": "1234",
},
});
- expect(res.status).toBe(304);
- expect(res.data).toBeNull();
+ expect(dataRes.status).toBe(304);
+ expect(dataRes.data).toBeNull();
});
test.describe("revalidations/_routes param", () => {
diff --git a/packages/remix-server-runtime/server.ts b/packages/remix-server-runtime/server.ts
index a28aff97369..14a7f680893 100644
--- a/packages/remix-server-runtime/server.ts
+++ b/packages/remix-server-runtime/server.ts
@@ -465,6 +465,11 @@ async function handleDocumentRequest(
let headers = getDocumentHeaders(build, context);
+ // 304 responses should not have a body or a content-type
+ if (context.statusCode === 304) {
+ return new Response(null, { status: 304, headers });
+ }
+
// Sanitize errors outside of development environments
if (context.errors) {
Object.values(context.errors).forEach((err) => {