From 7ee0eacfde99f8fff74274599c3ee7bdf2d656ff Mon Sep 17 00:00:00 2001
From: lilnasy <69170106+lilnasy@users.noreply.github.com>
Date: Mon, 14 Aug 2023 13:30:57 +0000
Subject: [PATCH 01/11] add tests for indirectly called prerendered 500 with
imported styles
---
.../ssr-prerender/src/external-stylesheet.css | 3 ++
.../ssr-prerender/src/nondeterminism.ts | 17 ++++++++++
.../ssr-prerender/src/pages/500.astro | 6 ++++
.../ssr-prerender/src/pages/fivehundred.astro | 4 +++
packages/astro/test/ssr-prerender.test.js | 33 +++++++++++++++++--
5 files changed, 61 insertions(+), 2 deletions(-)
create mode 100644 packages/astro/test/fixtures/ssr-prerender/src/external-stylesheet.css
create mode 100644 packages/astro/test/fixtures/ssr-prerender/src/nondeterminism.ts
create mode 100644 packages/astro/test/fixtures/ssr-prerender/src/pages/500.astro
create mode 100644 packages/astro/test/fixtures/ssr-prerender/src/pages/fivehundred.astro
diff --git a/packages/astro/test/fixtures/ssr-prerender/src/external-stylesheet.css b/packages/astro/test/fixtures/ssr-prerender/src/external-stylesheet.css
new file mode 100644
index 000000000000..5f331948a60d
--- /dev/null
+++ b/packages/astro/test/fixtures/ssr-prerender/src/external-stylesheet.css
@@ -0,0 +1,3 @@
+body {
+ background-color: ivory;
+}
diff --git a/packages/astro/test/fixtures/ssr-prerender/src/nondeterminism.ts b/packages/astro/test/fixtures/ssr-prerender/src/nondeterminism.ts
new file mode 100644
index 000000000000..8f8024a6083b
--- /dev/null
+++ b/packages/astro/test/fixtures/ssr-prerender/src/nondeterminism.ts
@@ -0,0 +1,17 @@
+// This module is only used by the prerendered 500.astro.
+// It exhibits different behavior if it's called more than once,
+// which is detected by a test and interpreted as a failure.
+
+let usedOnce = false
+let dynamicMessage = "Page was not prerendered"
+
+export default function () {
+ if (usedOnce === false) {
+ usedOnce = true
+ return "Something went wrong"
+ }
+
+ dynamicMessage += "+"
+
+ return dynamicMessage
+}
diff --git a/packages/astro/test/fixtures/ssr-prerender/src/pages/500.astro b/packages/astro/test/fixtures/ssr-prerender/src/pages/500.astro
new file mode 100644
index 000000000000..9b184a3de67f
--- /dev/null
+++ b/packages/astro/test/fixtures/ssr-prerender/src/pages/500.astro
@@ -0,0 +1,6 @@
+---
+import "../external-stylesheet.css"
+import message from "../nondeterminism"
+export const prerender = true
+---
+{message()}
\ No newline at end of file
diff --git a/packages/astro/test/fixtures/ssr-prerender/src/pages/fivehundred.astro b/packages/astro/test/fixtures/ssr-prerender/src/pages/fivehundred.astro
new file mode 100644
index 000000000000..99d103567db2
--- /dev/null
+++ b/packages/astro/test/fixtures/ssr-prerender/src/pages/fivehundred.astro
@@ -0,0 +1,4 @@
+---
+return new Response(null, { status: 500 })
+---
+
This html will not be served
diff --git a/packages/astro/test/ssr-prerender.test.js b/packages/astro/test/ssr-prerender.test.js
index 90ec1b6faa54..4d015552c9d9 100644
--- a/packages/astro/test/ssr-prerender.test.js
+++ b/packages/astro/test/ssr-prerender.test.js
@@ -30,8 +30,37 @@ describe('SSR: prerender', () => {
const app = await fixture.loadTestAdapterApp();
/** @type {Set} */
const assets = app.manifest.assets;
- expect(assets.size).to.equal(1);
- expect(Array.from(assets)[0].endsWith('static/index.html')).to.be.true;
+ expect(assets).to.contain('/static/index.html');
+ });
+
+ it('prerenders a 500 route', async () => {
+ const app = await fixture.loadTestAdapterApp();
+ const request = new Request('http://example.com/fivehundred');
+ const response1 = await app.render(request);
+ const response2 = await app.render(request);
+ const response3 = await app.render(request);
+
+ expect(response1.status).to.equal(500);
+
+ const html1 = await response1.text();
+ const html2 = await response2.text();
+ const html3 = await response3.text();
+
+ expect(html1).to.contain("Something went wrong");
+
+ expect(html1).to.equal(html2);
+ expect(html2).to.equal(html3);
+ });
+
+ it('includes expected styles in a redirected prerendered 500 route', async () => {
+ const app = await fixture.loadTestAdapterApp();
+ const request = new Request('http://example.com/fivehundred');
+ const response = await app.render(request);
+ const html = await response.text();
+ const $ = cheerio.load(html);
+
+ // length will be 0 if the stylesheet does not get included
+ expect($('link[rel=stylesheet]')).to.have.a.lengthOf(1);
});
});
From 553be786a029c5b3818930a5804900e98ea9e549 Mon Sep 17 00:00:00 2001
From: lilnasy <69170106+lilnasy@users.noreply.github.com>
Date: Mon, 14 Aug 2023 13:30:57 +0000
Subject: [PATCH 02/11] adjust tests for prerendered 404 routes
---
.../prerender-404/src/nondeterminism.ts | 17 ++++
.../prerender-404/src/pages/404.astro | 4 +-
.../node/test/prerender-404.test.js | 80 +++++++++++++++----
3 files changed, 83 insertions(+), 18 deletions(-)
create mode 100644 packages/integrations/node/test/fixtures/prerender-404/src/nondeterminism.ts
diff --git a/packages/integrations/node/test/fixtures/prerender-404/src/nondeterminism.ts b/packages/integrations/node/test/fixtures/prerender-404/src/nondeterminism.ts
new file mode 100644
index 000000000000..1795c26b07af
--- /dev/null
+++ b/packages/integrations/node/test/fixtures/prerender-404/src/nondeterminism.ts
@@ -0,0 +1,17 @@
+// This module is only used by the prerendered 404.astro.
+// It exhibits different behavior if it's called more than once,
+// which is detected by a test and interpreted as a failure.
+
+let usedOnce = false
+let dynamicMessage = "Page was not prerendered"
+
+export default function () {
+ if (usedOnce === false) {
+ usedOnce = true
+ return "Page does not exist"
+ }
+
+ dynamicMessage += "+"
+
+ return dynamicMessage
+}
diff --git a/packages/integrations/node/test/fixtures/prerender-404/src/pages/404.astro b/packages/integrations/node/test/fixtures/prerender-404/src/pages/404.astro
index 230402bbccdb..0f79f7f762a9 100644
--- a/packages/integrations/node/test/fixtures/prerender-404/src/pages/404.astro
+++ b/packages/integrations/node/test/fixtures/prerender-404/src/pages/404.astro
@@ -1,5 +1,5 @@
---
+import message from "../nondeterminism"
export const prerender = true;
---
-
-Page does not exist
+{message()}
diff --git a/packages/integrations/node/test/prerender-404.test.js b/packages/integrations/node/test/prerender-404.test.js
index 626f584e0c17..bdd39ab67bd6 100644
--- a/packages/integrations/node/test/prerender-404.test.js
+++ b/packages/integrations/node/test/prerender-404.test.js
@@ -52,11 +52,23 @@ describe('Prerender 404', () => {
});
it('Can handle prerendered 404', async () => {
- const res = await fetch(`http://${server.host}:${server.port}/some-base/missing`);
- const html = await res.text();
- const $ = cheerio.load(html);
+ const res1 = await fetch(`http://${server.host}:${server.port}/some-base/missing`);
+ const res2 = await fetch(`http://${server.host}:${server.port}/some-base/missing`);
+ const res3 = await fetch(`http://${server.host}:${server.port}/some-base/missing`);
+
+ expect(res1.status).to.equal(404);
+ expect(res2.status).to.equal(404);
+ expect(res3.status).to.equal(404);
+
+ const html1 = await res1.text();
+ const html2 = await res2.text();
+ const html3 = await res3.text();
+
+ expect(html1).to.equal(html2);
+ expect(html2).to.equal(html3);
+
+ const $ = cheerio.load(html1);
- expect(res.status).to.equal(404);
expect($('body').text()).to.equal('Page does not exist');
});
});
@@ -93,11 +105,23 @@ describe('Prerender 404', () => {
});
it('Can handle prerendered 404', async () => {
- const res = await fetch(`http://${server.host}:${server.port}/missing`);
- const html = await res.text();
- const $ = cheerio.load(html);
+ const res1 = await fetch(`http://${server.host}:${server.port}/missing`);
+ const res2 = await fetch(`http://${server.host}:${server.port}/missing`);
+ const res3 = await fetch(`http://${server.host}:${server.port}/missing`);
+
+ expect(res1.status).to.equal(404);
+ expect(res2.status).to.equal(404);
+ expect(res3.status).to.equal(404);
+
+ const html1 = await res1.text();
+ const html2 = await res2.text();
+ const html3 = await res3.text();
+
+ expect(html1).to.equal(html2);
+ expect(html2).to.equal(html3);
+
+ const $ = cheerio.load(html1);
- expect(res.status).to.equal(404);
expect($('body').text()).to.equal('Page does not exist');
});
});
@@ -140,11 +164,23 @@ describe('Hybrid 404', () => {
});
it('Can handle prerendered 404', async () => {
- const res = await fetch(`http://${server.host}:${server.port}/some-base/missing`);
- const html = await res.text();
- const $ = cheerio.load(html);
+ const res1 = await fetch(`http://${server.host}:${server.port}/some-base/missing`);
+ const res2 = await fetch(`http://${server.host}:${server.port}/some-base/missing`);
+ const res3 = await fetch(`http://${server.host}:${server.port}/some-base/missing`);
+
+ expect(res1.status).to.equal(404);
+ expect(res2.status).to.equal(404);
+ expect(res3.status).to.equal(404);
+
+ const html1 = await res1.text();
+ const html2 = await res2.text();
+ const html3 = await res3.text();
+
+ expect(html1).to.equal(html2);
+ expect(html2).to.equal(html3);
+
+ const $ = cheerio.load(html1);
- expect(res.status).to.equal(404);
expect($('body').text()).to.equal('Page does not exist');
});
});
@@ -180,11 +216,23 @@ describe('Hybrid 404', () => {
});
it('Can handle prerendered 404', async () => {
- const res = await fetch(`http://${server.host}:${server.port}/missing`);
- const html = await res.text();
- const $ = cheerio.load(html);
+ const res1 = await fetch(`http://${server.host}:${server.port}/missing`);
+ const res2 = await fetch(`http://${server.host}:${server.port}/missing`);
+ const res3 = await fetch(`http://${server.host}:${server.port}/missing`);
+
+ expect(res1.status).to.equal(404);
+ expect(res2.status).to.equal(404);
+ expect(res3.status).to.equal(404);
+
+ const html1 = await res1.text();
+ const html2 = await res2.text();
+ const html3 = await res3.text();
+
+ expect(html1).to.equal(html2);
+ expect(html2).to.equal(html3);
+
+ const $ = cheerio.load(html1);
- expect(res.status).to.equal(404);
expect($('body').text()).to.equal('Page does not exist');
});
});
From 33b1554ba91c6bcc635fe0112e05630b48a1078d Mon Sep 17 00:00:00 2001
From: lilnasy <69170106+lilnasy@users.noreply.github.com>
Date: Mon, 14 Aug 2023 13:30:58 +0000
Subject: [PATCH 03/11] remove console.log from node image test
---
packages/integrations/node/test/image.test.js | 3 ---
1 file changed, 3 deletions(-)
diff --git a/packages/integrations/node/test/image.test.js b/packages/integrations/node/test/image.test.js
index 0834bc175fa4..f3d9ea71f8f4 100644
--- a/packages/integrations/node/test/image.test.js
+++ b/packages/integrations/node/test/image.test.js
@@ -32,9 +32,6 @@ describe('Image endpoint', () => {
'/_image?href=/_astro/some_penguin.97ef5f92.png&w=50&f=webp'
);
- console.log(resImage);
- const content = resImage.text();
- console.log(content);
expect(resImage.status).to.equal(200);
});
});
From 25e1090a759cfd0641bad595d355cc1d3bc72bb9 Mon Sep 17 00:00:00 2001
From: lilnasy <69170106+lilnasy@users.noreply.github.com>
Date: Mon, 14 Aug 2023 13:30:58 +0000
Subject: [PATCH 04/11] also query entrySpecifiers for prerendered components
that need to turned into no-ops
---
packages/astro/src/core/build/static-build.ts | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts
index 28f496d91660..306576159b25 100644
--- a/packages/astro/src/core/build/static-build.ts
+++ b/packages/astro/src/core/build/static-build.ts
@@ -308,8 +308,12 @@ async function runPostBuildHooks(
async function cleanStaticOutput(opts: StaticBuildOptions, internals: BuildInternals) {
const allStaticFiles = new Set();
for (const pageData of eachPageData(internals)) {
- if (pageData.route.prerender)
- allStaticFiles.add(internals.pageToBundleMap.get(pageData.moduleSpecifier));
+ if (pageData.route.prerender) {
+ const { moduleSpecifier } = pageData;
+ const pageBundleId = internals.pageToBundleMap.get(moduleSpecifier);
+ const entryBundleId = internals.entrySpecifierToBundleMap.get(moduleSpecifier);
+ allStaticFiles.add(pageBundleId ?? entryBundleId);
+ }
}
const ssr = isServerLikeOutput(opts.settings.config);
const out = ssr
From dd87bb3768df39b8650929e0af026bbe2f5fe7aa Mon Sep 17 00:00:00 2001
From: lilnasy <69170106+lilnasy@users.noreply.github.com>
Date: Mon, 14 Aug 2023 13:30:59 +0000
Subject: [PATCH 05/11] handle default exports when converting prerendered
components into no-ops
---
packages/astro/src/core/build/static-build.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts
index 306576159b25..706a302c4a45 100644
--- a/packages/astro/src/core/build/static-build.ts
+++ b/packages/astro/src/core/build/static-build.ts
@@ -341,7 +341,8 @@ async function cleanStaticOutput(opts: StaticBuildOptions, internals: BuildInter
// Replace exports (only prerendered pages) with a noop
let value = 'const noop = () => {};';
for (const e of exports) {
- value += `\nexport const ${e.n} = noop;`;
+ if (e.n === 'default') value += `\n export default noop;`
+ else value += `\nexport const ${e.n} = noop;`;
}
await fs.promises.writeFile(url, value, { encoding: 'utf8' });
})
From a9670c101033b0d45217b6cdcced0fc1f02e46b1 Mon Sep 17 00:00:00 2001
From: lilnasy <69170106+lilnasy@users.noreply.github.com>
Date: Mon, 14 Aug 2023 16:23:46 +0000
Subject: [PATCH 06/11] fix tests
---
.../test/fixtures/prerender-404/package.json | 1 +
.../node/test/prerender-404.test.js | 23 ++++++++++++++++---
2 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/packages/integrations/node/test/fixtures/prerender-404/package.json b/packages/integrations/node/test/fixtures/prerender-404/package.json
index dfd109c9142f..2a0fdc30c835 100644
--- a/packages/integrations/node/test/fixtures/prerender-404/package.json
+++ b/packages/integrations/node/test/fixtures/prerender-404/package.json
@@ -2,6 +2,7 @@
"name": "@test/nodejs-prerender-404",
"version": "0.0.0",
"private": true,
+ "type": "module",
"dependencies": {
"astro": "workspace:*",
"@astrojs/node": "workspace:*"
diff --git a/packages/integrations/node/test/prerender-404.test.js b/packages/integrations/node/test/prerender-404.test.js
index bdd39ab67bd6..811bbdf764d3 100644
--- a/packages/integrations/node/test/prerender-404.test.js
+++ b/packages/integrations/node/test/prerender-404.test.js
@@ -14,6 +14,7 @@ async function load() {
);
return mod;
}
+
describe('Prerender 404', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
@@ -25,6 +26,10 @@ describe('Prerender 404', () => {
process.env.PRERENDER = true;
fixture = await loadFixture({
+ // inconsequential config that differs between tests
+ // to bust cache and prevent modules and their state
+ // from being reused
+ site: 'https://test.dev/',
base: '/some-base',
root: './fixtures/prerender-404/',
output: 'server',
@@ -79,12 +84,16 @@ describe('Prerender 404', () => {
process.env.PRERENDER = true;
fixture = await loadFixture({
+ // inconsequential config that differs between tests
+ // to bust cache and prevent modules and their state
+ // from being reused
+ site: 'https://test.info/',
root: './fixtures/prerender-404/',
output: 'server',
adapter: nodejs({ mode: 'standalone' }),
});
await fixture.build();
- const { startServer } = await await load();
+ const { startServer } = await load();
let res = startServer();
server = res.server;
});
@@ -137,13 +146,17 @@ describe('Hybrid 404', () => {
process.env.ASTRO_NODE_AUTOSTART = 'disabled';
process.env.PRERENDER = false;
fixture = await loadFixture({
+ // inconsequential config that differs between tests
+ // to bust cache and prevent modules and their state
+ // from being reused
+ site: 'https://test.com/',
base: '/some-base',
root: './fixtures/prerender-404/',
output: 'hybrid',
adapter: nodejs({ mode: 'standalone' }),
});
await fixture.build();
- const { startServer } = await await load();
+ const { startServer } = await load();
let res = startServer();
server = res.server;
});
@@ -190,12 +203,16 @@ describe('Hybrid 404', () => {
process.env.ASTRO_NODE_AUTOSTART = 'disabled';
process.env.PRERENDER = false;
fixture = await loadFixture({
+ // inconsequential config that differs between tests
+ // to bust cache and prevent modules and their state
+ // from being reused
+ site: 'https://test.net/',
root: './fixtures/prerender-404/',
output: 'hybrid',
adapter: nodejs({ mode: 'standalone' }),
});
await fixture.build();
- const { startServer } = await await load();
+ const { startServer } = await load();
let res = startServer();
server = res.server;
});
From 26a5f2516973de443af357ad2172c56687923b03 Mon Sep 17 00:00:00 2001
From: lilnasy <69170106+lilnasy@users.noreply.github.com>
Date: Mon, 14 Aug 2023 18:01:50 +0000
Subject: [PATCH 07/11] move 500 test to node integration
---
packages/astro/test/ssr-prerender.test.js | 30 ---------
.../package.json | 2 +-
.../src/external-stylesheet.css | 0
.../src/nondeterminism-404.ts} | 0
.../src/nondeterminism-500.ts} | 0
.../src/pages/404.astro | 2 +-
.../prerender-404-500}/src/pages/500.astro | 2 +-
.../src/pages/fivehundred.astro | 0
.../src/pages/static.astro | 0
...-404.test.js => prerender-404-500.test.js} | 66 ++++++++++++++-----
10 files changed, 52 insertions(+), 50 deletions(-)
rename packages/integrations/node/test/fixtures/{prerender-404 => prerender-404-500}/package.json (77%)
rename packages/{astro/test/fixtures/ssr-prerender => integrations/node/test/fixtures/prerender-404-500}/src/external-stylesheet.css (100%)
rename packages/integrations/node/test/fixtures/{prerender-404/src/nondeterminism.ts => prerender-404-500/src/nondeterminism-404.ts} (100%)
rename packages/{astro/test/fixtures/ssr-prerender/src/nondeterminism.ts => integrations/node/test/fixtures/prerender-404-500/src/nondeterminism-500.ts} (100%)
rename packages/integrations/node/test/fixtures/{prerender-404 => prerender-404-500}/src/pages/404.astro (53%)
rename packages/{astro/test/fixtures/ssr-prerender => integrations/node/test/fixtures/prerender-404-500}/src/pages/500.astro (65%)
rename packages/{astro/test/fixtures/ssr-prerender => integrations/node/test/fixtures/prerender-404-500}/src/pages/fivehundred.astro (100%)
rename packages/integrations/node/test/fixtures/{prerender-404 => prerender-404-500}/src/pages/static.astro (100%)
rename packages/integrations/node/test/{prerender-404.test.js => prerender-404-500.test.js} (77%)
diff --git a/packages/astro/test/ssr-prerender.test.js b/packages/astro/test/ssr-prerender.test.js
index 4d015552c9d9..567371f0bbaa 100644
--- a/packages/astro/test/ssr-prerender.test.js
+++ b/packages/astro/test/ssr-prerender.test.js
@@ -32,36 +32,6 @@ describe('SSR: prerender', () => {
const assets = app.manifest.assets;
expect(assets).to.contain('/static/index.html');
});
-
- it('prerenders a 500 route', async () => {
- const app = await fixture.loadTestAdapterApp();
- const request = new Request('http://example.com/fivehundred');
- const response1 = await app.render(request);
- const response2 = await app.render(request);
- const response3 = await app.render(request);
-
- expect(response1.status).to.equal(500);
-
- const html1 = await response1.text();
- const html2 = await response2.text();
- const html3 = await response3.text();
-
- expect(html1).to.contain("Something went wrong");
-
- expect(html1).to.equal(html2);
- expect(html2).to.equal(html3);
- });
-
- it('includes expected styles in a redirected prerendered 500 route', async () => {
- const app = await fixture.loadTestAdapterApp();
- const request = new Request('http://example.com/fivehundred');
- const response = await app.render(request);
- const html = await response.text();
- const $ = cheerio.load(html);
-
- // length will be 0 if the stylesheet does not get included
- expect($('link[rel=stylesheet]')).to.have.a.lengthOf(1);
- });
});
describe('Astro.params in SSR', () => {
diff --git a/packages/integrations/node/test/fixtures/prerender-404/package.json b/packages/integrations/node/test/fixtures/prerender-404-500/package.json
similarity index 77%
rename from packages/integrations/node/test/fixtures/prerender-404/package.json
rename to packages/integrations/node/test/fixtures/prerender-404-500/package.json
index 2a0fdc30c835..f962fe991e3f 100644
--- a/packages/integrations/node/test/fixtures/prerender-404/package.json
+++ b/packages/integrations/node/test/fixtures/prerender-404-500/package.json
@@ -1,5 +1,5 @@
{
- "name": "@test/nodejs-prerender-404",
+ "name": "@test/nodejs-prerender-404-500",
"version": "0.0.0",
"private": true,
"type": "module",
diff --git a/packages/astro/test/fixtures/ssr-prerender/src/external-stylesheet.css b/packages/integrations/node/test/fixtures/prerender-404-500/src/external-stylesheet.css
similarity index 100%
rename from packages/astro/test/fixtures/ssr-prerender/src/external-stylesheet.css
rename to packages/integrations/node/test/fixtures/prerender-404-500/src/external-stylesheet.css
diff --git a/packages/integrations/node/test/fixtures/prerender-404/src/nondeterminism.ts b/packages/integrations/node/test/fixtures/prerender-404-500/src/nondeterminism-404.ts
similarity index 100%
rename from packages/integrations/node/test/fixtures/prerender-404/src/nondeterminism.ts
rename to packages/integrations/node/test/fixtures/prerender-404-500/src/nondeterminism-404.ts
diff --git a/packages/astro/test/fixtures/ssr-prerender/src/nondeterminism.ts b/packages/integrations/node/test/fixtures/prerender-404-500/src/nondeterminism-500.ts
similarity index 100%
rename from packages/astro/test/fixtures/ssr-prerender/src/nondeterminism.ts
rename to packages/integrations/node/test/fixtures/prerender-404-500/src/nondeterminism-500.ts
diff --git a/packages/integrations/node/test/fixtures/prerender-404/src/pages/404.astro b/packages/integrations/node/test/fixtures/prerender-404-500/src/pages/404.astro
similarity index 53%
rename from packages/integrations/node/test/fixtures/prerender-404/src/pages/404.astro
rename to packages/integrations/node/test/fixtures/prerender-404-500/src/pages/404.astro
index 0f79f7f762a9..37fd1c1d39c4 100644
--- a/packages/integrations/node/test/fixtures/prerender-404/src/pages/404.astro
+++ b/packages/integrations/node/test/fixtures/prerender-404-500/src/pages/404.astro
@@ -1,5 +1,5 @@
---
-import message from "../nondeterminism"
+import message from "../nondeterminism-404"
export const prerender = true;
---
{message()}
diff --git a/packages/astro/test/fixtures/ssr-prerender/src/pages/500.astro b/packages/integrations/node/test/fixtures/prerender-404-500/src/pages/500.astro
similarity index 65%
rename from packages/astro/test/fixtures/ssr-prerender/src/pages/500.astro
rename to packages/integrations/node/test/fixtures/prerender-404-500/src/pages/500.astro
index 9b184a3de67f..3aa51803459f 100644
--- a/packages/astro/test/fixtures/ssr-prerender/src/pages/500.astro
+++ b/packages/integrations/node/test/fixtures/prerender-404-500/src/pages/500.astro
@@ -1,6 +1,6 @@
---
import "../external-stylesheet.css"
-import message from "../nondeterminism"
+import message from "../nondeterminism-500"
export const prerender = true
---
{message()}
\ No newline at end of file
diff --git a/packages/astro/test/fixtures/ssr-prerender/src/pages/fivehundred.astro b/packages/integrations/node/test/fixtures/prerender-404-500/src/pages/fivehundred.astro
similarity index 100%
rename from packages/astro/test/fixtures/ssr-prerender/src/pages/fivehundred.astro
rename to packages/integrations/node/test/fixtures/prerender-404-500/src/pages/fivehundred.astro
diff --git a/packages/integrations/node/test/fixtures/prerender-404/src/pages/static.astro b/packages/integrations/node/test/fixtures/prerender-404-500/src/pages/static.astro
similarity index 100%
rename from packages/integrations/node/test/fixtures/prerender-404/src/pages/static.astro
rename to packages/integrations/node/test/fixtures/prerender-404-500/src/pages/static.astro
diff --git a/packages/integrations/node/test/prerender-404.test.js b/packages/integrations/node/test/prerender-404-500.test.js
similarity index 77%
rename from packages/integrations/node/test/prerender-404.test.js
rename to packages/integrations/node/test/prerender-404-500.test.js
index 811bbdf764d3..ab3dd8c149c0 100644
--- a/packages/integrations/node/test/prerender-404.test.js
+++ b/packages/integrations/node/test/prerender-404-500.test.js
@@ -10,7 +10,7 @@ import { fetch } from 'undici';
async function load() {
const mod = await import(
- `./fixtures/prerender-404/dist/server/entry.mjs?dropcache=${Date.now()}`
+ `./fixtures/prerender-404-500/dist/server/entry.mjs?dropcache=${Date.now()}`
);
return mod;
}
@@ -31,7 +31,7 @@ describe('Prerender 404', () => {
// from being reused
site: 'https://test.dev/',
base: '/some-base',
- root: './fixtures/prerender-404/',
+ root: './fixtures/prerender-404-500/',
output: 'server',
adapter: nodejs({ mode: 'standalone' }),
});
@@ -57,9 +57,10 @@ describe('Prerender 404', () => {
});
it('Can handle prerendered 404', async () => {
- const res1 = await fetch(`http://${server.host}:${server.port}/some-base/missing`);
- const res2 = await fetch(`http://${server.host}:${server.port}/some-base/missing`);
- const res3 = await fetch(`http://${server.host}:${server.port}/some-base/missing`);
+ const url = `http://${server.host}:${server.port}/some-base/missing`;
+ const res1 = await fetch(url);
+ const res2 = await fetch(url);
+ const res3 = await fetch(url);
expect(res1.status).to.equal(404);
expect(res2.status).to.equal(404);
@@ -76,6 +77,34 @@ describe('Prerender 404', () => {
expect($('body').text()).to.equal('Page does not exist');
});
+
+ it('serves prerendered 500 indirectly', async () => {
+ const url = `http://${server.host}:${server.port}/some-base/fivehundred`;
+ const response1 = await fetch(url);
+ const response2 = await fetch(url);
+ const response3 = await fetch(url);
+
+ expect(response1.status).to.equal(500);
+
+ const html1 = await response1.text();
+ const html2 = await response2.text();
+ const html3 = await response3.text();
+
+ expect(html1).to.contain("Something went wrong");
+
+ expect(html1).to.equal(html2);
+ expect(html2).to.equal(html3);
+ });
+
+ it('prerendered 500 page includes expected styles', async () => {
+ const response = await fetch(`http://${server.host}:${server.port}/some-base/fivehundred`);
+ const html = await response.text();
+ const $ = cheerio.load(html);
+
+ // length will be 0 if the stylesheet does not get included
+ expect($('link[rel=stylesheet]')).to.have.a.lengthOf(1);
+ });
+
});
describe('Without base', async () => {
@@ -88,7 +117,7 @@ describe('Prerender 404', () => {
// to bust cache and prevent modules and their state
// from being reused
site: 'https://test.info/',
- root: './fixtures/prerender-404/',
+ root: './fixtures/prerender-404-500/',
output: 'server',
adapter: nodejs({ mode: 'standalone' }),
});
@@ -114,9 +143,10 @@ describe('Prerender 404', () => {
});
it('Can handle prerendered 404', async () => {
- const res1 = await fetch(`http://${server.host}:${server.port}/missing`);
- const res2 = await fetch(`http://${server.host}:${server.port}/missing`);
- const res3 = await fetch(`http://${server.host}:${server.port}/missing`);
+ const url = `http://${server.host}:${server.port}/some-base/missing`
+ const res1 = await fetch(url);
+ const res2 = await fetch(url);
+ const res3 = await fetch(url);
expect(res1.status).to.equal(404);
expect(res2.status).to.equal(404);
@@ -151,7 +181,7 @@ describe('Hybrid 404', () => {
// from being reused
site: 'https://test.com/',
base: '/some-base',
- root: './fixtures/prerender-404/',
+ root: './fixtures/prerender-404-500/',
output: 'hybrid',
adapter: nodejs({ mode: 'standalone' }),
});
@@ -177,9 +207,10 @@ describe('Hybrid 404', () => {
});
it('Can handle prerendered 404', async () => {
- const res1 = await fetch(`http://${server.host}:${server.port}/some-base/missing`);
- const res2 = await fetch(`http://${server.host}:${server.port}/some-base/missing`);
- const res3 = await fetch(`http://${server.host}:${server.port}/some-base/missing`);
+ const url = `http://${server.host}:${server.port}/some-base/missing`
+ const res1 = await fetch(url);
+ const res2 = await fetch(url);
+ const res3 = await fetch(url);
expect(res1.status).to.equal(404);
expect(res2.status).to.equal(404);
@@ -207,7 +238,7 @@ describe('Hybrid 404', () => {
// to bust cache and prevent modules and their state
// from being reused
site: 'https://test.net/',
- root: './fixtures/prerender-404/',
+ root: './fixtures/prerender-404-500/',
output: 'hybrid',
adapter: nodejs({ mode: 'standalone' }),
});
@@ -233,9 +264,10 @@ describe('Hybrid 404', () => {
});
it('Can handle prerendered 404', async () => {
- const res1 = await fetch(`http://${server.host}:${server.port}/missing`);
- const res2 = await fetch(`http://${server.host}:${server.port}/missing`);
- const res3 = await fetch(`http://${server.host}:${server.port}/missing`);
+ const url = `http://${server.host}:${server.port}/missing`
+ const res1 = await fetch(url);
+ const res2 = await fetch(url);
+ const res3 = await fetch(url);
expect(res1.status).to.equal(404);
expect(res2.status).to.equal(404);
From 8325549f33b0ec8ec02ea8a2b5054374d6a51ed9 Mon Sep 17 00:00:00 2001
From: lilnasy <69170106+lilnasy@users.noreply.github.com>
Date: Tue, 15 Aug 2023 00:34:17 +0000
Subject: [PATCH 08/11] make request for static html when an error route is
prerendered
---
packages/astro/src/core/app/index.ts | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/packages/astro/src/core/app/index.ts b/packages/astro/src/core/app/index.ts
index bec5368b6ce2..9afc010bd819 100644
--- a/packages/astro/src/core/app/index.ts
+++ b/packages/astro/src/core/app/index.ts
@@ -286,8 +286,9 @@ export class App {
const errorRouteData = matchRoute('/' + status, this.#manifestData);
const url = new URL(request.url);
if (errorRouteData) {
- if (errorRouteData.prerender && !errorRouteData.route.endsWith(`/${status}`)) {
- const statusURL = new URL(`${this.#baseWithoutTrailingSlash}/${status}`, url);
+ if (errorRouteData.prerender){
+ const maybeDotHtml = errorRouteData.route.endsWith(`/${status}`) ? '.html' : ''
+ const statusURL = new URL(`${this.#baseWithoutTrailingSlash}/${status}${maybeDotHtml}`, url);
const response = await fetch(statusURL.toString());
return this.#mergeResponses(response, originalResponse);
}
From c11e75ab1c28af7abcbc4e99ddff59e473d63b5c Mon Sep 17 00:00:00 2001
From: lilnasy <69170106+lilnasy@users.noreply.github.com>
Date: Tue, 15 Aug 2023 00:59:09 +0000
Subject: [PATCH 09/11] update pnpm-lock.yaml
---
pnpm-lock.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 48cd6243367e..6d956cca8a8c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -4677,7 +4677,7 @@ importers:
specifier: workspace:*
version: link:../../../../../astro
- packages/integrations/node/test/fixtures/prerender-404:
+ packages/integrations/node/test/fixtures/prerender-404-500:
dependencies:
'@astrojs/node':
specifier: workspace:*
From 0e123ee20ed4dc3f34d8caf17b6bae5556b5c1b7 Mon Sep 17 00:00:00 2001
From: lilnasy <69170106+lilnasy@users.noreply.github.com>
Date: Tue, 15 Aug 2023 18:28:43 +0000
Subject: [PATCH 10/11] fix status codes from static files
---
packages/astro/src/core/app/index.ts | 35 +++++++++++++++----
.../prerender-404-500/src/pages/500.astro | 2 +-
.../node/test/prerender-404-500.test.js | 2 +-
3 files changed, 30 insertions(+), 9 deletions(-)
diff --git a/packages/astro/src/core/app/index.ts b/packages/astro/src/core/app/index.ts
index 9afc010bd819..900efc682293 100644
--- a/packages/astro/src/core/app/index.ts
+++ b/packages/astro/src/core/app/index.ts
@@ -290,7 +290,12 @@ export class App {
const maybeDotHtml = errorRouteData.route.endsWith(`/${status}`) ? '.html' : ''
const statusURL = new URL(`${this.#baseWithoutTrailingSlash}/${status}${maybeDotHtml}`, url);
const response = await fetch(statusURL.toString());
- return this.#mergeResponses(response, originalResponse);
+
+ // response for /404.html and 500.html is 200, which is not meaningful
+ // so we create an override
+ const override = { status }
+
+ return this.#mergeResponses(response, originalResponse, override);
}
const mod = await this.#getModuleForRoute(errorRouteData);
try {
@@ -317,14 +322,30 @@ export class App {
return response;
}
- #mergeResponses(newResponse: Response, oldResponse?: Response) {
- if (!oldResponse) return newResponse;
- const { status, statusText, headers } = oldResponse;
+ #mergeResponses(newResponse: Response, oldResponse?: Response, override?: { status : 404 | 500 }) {
+ if (!oldResponse) {
+ if (override !== undefined) {
+ return new Response(newResponse.body, {
+ status: override.status,
+ statusText: newResponse.statusText,
+ headers: newResponse.headers
+ })
+ }
+ return newResponse;
+ }
+
+ const { statusText, headers } = oldResponse;
+
+ // If the the new response did not have a meaningful status, an override may have been provided
+ // If the original status was 200 (default), override it with the new status (probably 404 or 500)
+ // Otherwise, the user set a specific status while rendering and we should respect that one
+ const status =
+ override?.status ? override.status :
+ oldResponse.status === 200 ? newResponse.status :
+ oldResponse.status
return new Response(newResponse.body, {
- // If the original status was 200 (default), override it with the new status (probably 404 or 500)
- // Otherwise, the user set a specific status while rendering and we should respect that one
- status: status === 200 ? newResponse.status : status,
+ status,
statusText: status === 200 ? newResponse.statusText : statusText,
headers: new Headers(Array.from(headers)),
});
diff --git a/packages/integrations/node/test/fixtures/prerender-404-500/src/pages/500.astro b/packages/integrations/node/test/fixtures/prerender-404-500/src/pages/500.astro
index 3aa51803459f..ef91ad0ffa91 100644
--- a/packages/integrations/node/test/fixtures/prerender-404-500/src/pages/500.astro
+++ b/packages/integrations/node/test/fixtures/prerender-404-500/src/pages/500.astro
@@ -3,4 +3,4 @@ import "../external-stylesheet.css"
import message from "../nondeterminism-500"
export const prerender = true
---
-{message()}
\ No newline at end of file
+{message()}
diff --git a/packages/integrations/node/test/prerender-404-500.test.js b/packages/integrations/node/test/prerender-404-500.test.js
index ab3dd8c149c0..33cebab5ba4a 100644
--- a/packages/integrations/node/test/prerender-404-500.test.js
+++ b/packages/integrations/node/test/prerender-404-500.test.js
@@ -78,7 +78,7 @@ describe('Prerender 404', () => {
expect($('body').text()).to.equal('Page does not exist');
});
- it('serves prerendered 500 indirectly', async () => {
+ it(' Can handle prerendered 500 called indirectly', async () => {
const url = `http://${server.host}:${server.port}/some-base/fivehundred`;
const response1 = await fetch(url);
const response2 = await fetch(url);
From ae2d417a163f15565c69f8ac508196314cd2b77a Mon Sep 17 00:00:00 2001
From: Nate Moore
Date: Tue, 15 Aug 2023 15:36:59 -0500
Subject: [PATCH 11/11] Create many-actors-flash.md
---
.changeset/many-actors-flash.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 .changeset/many-actors-flash.md
diff --git a/.changeset/many-actors-flash.md b/.changeset/many-actors-flash.md
new file mode 100644
index 000000000000..92f70c55a024
--- /dev/null
+++ b/.changeset/many-actors-flash.md
@@ -0,0 +1,5 @@
+---
+"astro": patch
+---
+
+Fix a handful of edge cases with prerendered 404/500 pages