new demo mode & tenure
This commit is contained in:
parent
7656f24544
commit
4a0f00f2a4
64 changed files with 2875 additions and 338 deletions
|
|
@ -12,9 +12,9 @@ const ROUTES = [
|
|||
{
|
||||
path: '/',
|
||||
output: 'index.html',
|
||||
title: 'Stop searching the wrong places | Perfect Postcode',
|
||||
title: 'Find the best-value postcode in England | Perfect Postcode',
|
||||
description:
|
||||
'Filter every postcode in England by budget, commute, schools, crime, noise, broadband, property prices and amenities before you start chasing viewings.',
|
||||
'Rank every postcode in England by value: £/sqm, sold prices, schools, commute, crime, noise and broadband. Find the underpriced postcode the market overlooked.',
|
||||
},
|
||||
{
|
||||
path: '/learn',
|
||||
|
|
@ -345,64 +345,64 @@ async function prerender() {
|
|||
const MAX_ATTEMPTS = 3;
|
||||
|
||||
async function renderRoute(route) {
|
||||
// A fresh context per attempt: pages otherwise share cache/storage, and a
|
||||
// poisoned chunk-fetch in the shared cache makes a route fail every retry.
|
||||
const context = await browser.createBrowserContext();
|
||||
const page = await context.newPage();
|
||||
// A fresh context per attempt: pages otherwise share cache/storage, and a
|
||||
// poisoned chunk-fetch in the shared cache makes a route fail every retry.
|
||||
const context = await browser.createBrowserContext();
|
||||
const page = await context.newPage();
|
||||
|
||||
// Intercept API requests to prevent real fetches and retry loops.
|
||||
await page.setRequestInterception(true);
|
||||
page.on('request', (req) => {
|
||||
const url = req.url();
|
||||
if (url.includes('/api/features')) {
|
||||
req.respond({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ groups: [] }),
|
||||
});
|
||||
} else if (url.includes('/api/poi-categories')) {
|
||||
req.respond({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ groups: [] }),
|
||||
});
|
||||
} else if (url.includes('/api/pricing')) {
|
||||
req.respond({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({
|
||||
licensed_count: 120,
|
||||
current_price_pence: 999,
|
||||
tiers: [
|
||||
{ up_to: 50, price_pence: 99, slots: 50 },
|
||||
{ up_to: 150, price_pence: 999, slots: 100 },
|
||||
{ up_to: 250, price_pence: 2999, slots: 100 },
|
||||
{ up_to: 350, price_pence: 4999, slots: 100 },
|
||||
{ up_to: null, price_pence: 9999, slots: 0 },
|
||||
],
|
||||
}),
|
||||
});
|
||||
} else if (url.includes('/api/')) {
|
||||
req.respond({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: '{}',
|
||||
});
|
||||
} else {
|
||||
req.continue();
|
||||
}
|
||||
// Intercept API requests to prevent real fetches and retry loops.
|
||||
await page.setRequestInterception(true);
|
||||
page.on('request', (req) => {
|
||||
const url = req.url();
|
||||
if (url.includes('/api/features')) {
|
||||
req.respond({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ groups: [] }),
|
||||
});
|
||||
} else if (url.includes('/api/poi-categories')) {
|
||||
req.respond({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ groups: [] }),
|
||||
});
|
||||
} else if (url.includes('/api/pricing')) {
|
||||
req.respond({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({
|
||||
licensed_count: 120,
|
||||
current_price_pence: 999,
|
||||
tiers: [
|
||||
{ up_to: 50, price_pence: 99, slots: 50 },
|
||||
{ up_to: 150, price_pence: 999, slots: 100 },
|
||||
{ up_to: 250, price_pence: 2999, slots: 100 },
|
||||
{ up_to: 350, price_pence: 4999, slots: 100 },
|
||||
{ up_to: null, price_pence: 9999, slots: 0 },
|
||||
],
|
||||
}),
|
||||
});
|
||||
} else if (url.includes('/api/')) {
|
||||
req.respond({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: '{}',
|
||||
});
|
||||
} else {
|
||||
req.continue();
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
await page.goto(`http://127.0.0.1:${port}${route.path}`, {
|
||||
waitUntil: 'networkidle0',
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
try {
|
||||
await page.goto(`http://127.0.0.1:${port}${route.path}`, {
|
||||
waitUntil: 'networkidle0',
|
||||
timeout: 30000,
|
||||
});
|
||||
await page.waitForSelector('h1', { timeout: 10000 });
|
||||
|
||||
await page.waitForSelector('h1', { timeout: 10000 });
|
||||
|
||||
// Extract and clean the rendered HTML.
|
||||
const html = await page.evaluate(() => {
|
||||
// Extract and clean the rendered HTML.
|
||||
const html = await page.evaluate(() => {
|
||||
const root = document.getElementById('root');
|
||||
if (!root) return '';
|
||||
|
||||
|
|
@ -420,18 +420,18 @@ async function prerender() {
|
|||
});
|
||||
|
||||
return root.innerHTML;
|
||||
});
|
||||
});
|
||||
|
||||
if (!html || html.length < MIN_HTML_CHARS) {
|
||||
throw new Error(
|
||||
`Prerender produced too little HTML for ${route.path} (${html?.length ?? 0} chars)`
|
||||
);
|
||||
}
|
||||
|
||||
return html;
|
||||
} finally {
|
||||
await context.close().catch(() => {});
|
||||
if (!html || html.length < MIN_HTML_CHARS) {
|
||||
throw new Error(
|
||||
`Prerender produced too little HTML for ${route.path} (${html?.length ?? 0} chars)`
|
||||
);
|
||||
}
|
||||
|
||||
return html;
|
||||
} finally {
|
||||
await context.close().catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue