fix: puppeteer
This commit is contained in:
parent
5c3d55966e
commit
8f1d4f979c
@ -1,6 +1,18 @@
|
||||
// app/api/seo-check/route.js
|
||||
import { NextResponse } from "next/server";
|
||||
import puppeteer from "puppeteer";
|
||||
import puppeteer from "puppeteer-core";
|
||||
|
||||
// Helper function to get Chrome executable path
|
||||
function getChromePath() {
|
||||
if (process.env.AWS_LAMBDA_FUNCTION_VERSION) {
|
||||
return "/usr/bin/chromium-browser";
|
||||
}
|
||||
return process.platform === "win32"
|
||||
? "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe"
|
||||
: process.platform === "darwin"
|
||||
? "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
|
||||
: "/usr/bin/google-chrome";
|
||||
}
|
||||
|
||||
export async function POST(request) {
|
||||
const startTime = Date.now();
|
||||
@ -37,20 +49,31 @@ export async function POST(request) {
|
||||
let browser;
|
||||
try {
|
||||
browser = await puppeteer.launch({
|
||||
headless: true,
|
||||
executablePath: process.env.NEXT_CHROMIUM_PATH || '/usr/bin/chromium-browser',
|
||||
headless: "new",
|
||||
args: [
|
||||
"--no-sandbox",
|
||||
"--disable-setuid-sandbox",
|
||||
"--disable-dev-shm-usage",
|
||||
"--disable-accelerated-2d-canvas",
|
||||
"--no-first-run",
|
||||
"--no-zygote",
|
||||
"--single-process",
|
||||
"--disable-gpu",
|
||||
],
|
||||
timeout: 15000,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("Browser launch error:", e);
|
||||
return NextResponse.json(
|
||||
{ error: "Failed to initialize browser" },
|
||||
{ error: `Failed to initialize browser: ${e.message}` },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
|
||||
let page;
|
||||
let finalUrl;
|
||||
let html;
|
||||
let securityHeaders = {};
|
||||
let response;
|
||||
|
||||
try {
|
||||
page = await browser.newPage();
|
||||
@ -63,7 +86,6 @@ export async function POST(request) {
|
||||
// Listen for response to capture headers
|
||||
page.on("response", async (res) => {
|
||||
if (res.url() === url || res.url() === finalUrl) {
|
||||
response = res;
|
||||
securityHeaders = {
|
||||
https: res.url().startsWith("https://"),
|
||||
xFrameOptions: res.headers()["x-frame-options"],
|
||||
@ -82,11 +104,9 @@ export async function POST(request) {
|
||||
|
||||
// Get final URL after potential redirects
|
||||
finalUrl = page.url();
|
||||
|
||||
// Get the full HTML content
|
||||
html = await page.content();
|
||||
} catch (e) {
|
||||
await browser.close();
|
||||
console.error("Page navigation error:", e);
|
||||
return NextResponse.json(
|
||||
{
|
||||
error:
|
||||
@ -98,53 +118,66 @@ export async function POST(request) {
|
||||
);
|
||||
}
|
||||
|
||||
// Use Puppeteer's DOM methods for analysis
|
||||
const analysis = {
|
||||
url: finalUrl,
|
||||
pageLoadTime: (Date.now() - startTime) / 1000,
|
||||
title: await analyzeTitle(page),
|
||||
meta: {
|
||||
description: await analyzeMetaDescription(page),
|
||||
robots: await analyzeMetaRobots(page),
|
||||
viewport: await analyzeViewport(page),
|
||||
charset: await analyzeCharset(page),
|
||||
keywords: await getMetaContent(page, "keywords"),
|
||||
},
|
||||
headings: await analyzeHeadings(page),
|
||||
images: await analyzeImages(page),
|
||||
links: await analyzeLinks(page, finalUrl),
|
||||
content: await analyzeContent(page),
|
||||
technical: {
|
||||
canonical: await analyzeCanonical(page),
|
||||
language: await analyzeLanguage(page),
|
||||
schemaMarkup: await analyzeSchemaMarkup(page),
|
||||
doctype: await analyzeDoctype(page),
|
||||
},
|
||||
social: {
|
||||
openGraph: {
|
||||
title: await getMetaContent(page, "og:title"),
|
||||
description: await getMetaContent(page, "og:description"),
|
||||
image: await getMetaContent(page, "og:image"),
|
||||
url: await getMetaContent(page, "og:url"),
|
||||
try {
|
||||
// Use Puppeteer's DOM methods for analysis
|
||||
const analysis = {
|
||||
url: finalUrl,
|
||||
pageLoadTime: (Date.now() - startTime) / 1000,
|
||||
title: await analyzeTitle(page),
|
||||
meta: {
|
||||
description: await analyzeMetaDescription(page),
|
||||
robots: await analyzeMetaRobots(page),
|
||||
viewport: await analyzeViewport(page),
|
||||
charset: await analyzeCharset(page),
|
||||
keywords: await getMetaContent(page, "keywords"),
|
||||
},
|
||||
twitterCard: {
|
||||
card: await getMetaContent(page, "twitter:card"),
|
||||
title: await getMetaContent(page, "twitter:title"),
|
||||
description: await getMetaContent(page, "twitter:description"),
|
||||
image: await getMetaContent(page, "twitter:image"),
|
||||
headings: await analyzeHeadings(page),
|
||||
images: await analyzeImages(page),
|
||||
links: await analyzeLinks(page, finalUrl),
|
||||
content: await analyzeContent(page),
|
||||
technical: {
|
||||
canonical: await analyzeCanonical(page),
|
||||
language: await analyzeLanguage(page),
|
||||
schemaMarkup: await analyzeSchemaMarkup(page),
|
||||
doctype: await analyzeDoctype(page),
|
||||
},
|
||||
},
|
||||
security: securityHeaders,
|
||||
analyzedAt: new Date().toISOString(),
|
||||
};
|
||||
social: {
|
||||
openGraph: {
|
||||
title: await getMetaContent(page, "og:title"),
|
||||
description: await getMetaContent(page, "og:description"),
|
||||
image: await getMetaContent(page, "og:image"),
|
||||
url: await getMetaContent(page, "og:url"),
|
||||
},
|
||||
twitterCard: {
|
||||
card: await getMetaContent(page, "twitter:card"),
|
||||
title: await getMetaContent(page, "twitter:title"),
|
||||
description: await getMetaContent(page, "twitter:description"),
|
||||
image: await getMetaContent(page, "twitter:image"),
|
||||
},
|
||||
},
|
||||
security: securityHeaders,
|
||||
analyzedAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
await browser.close();
|
||||
return NextResponse.json(analysis);
|
||||
await browser.close();
|
||||
return NextResponse.json(analysis);
|
||||
} catch (error) {
|
||||
await browser.close();
|
||||
console.error("SEO analysis error:", error);
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: "Internal server error during analysis",
|
||||
details:
|
||||
process.env.NODE_ENV === "development" ? error.stack : undefined,
|
||||
},
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("SEO analysis error:", error);
|
||||
console.error("Unexpected error:", error);
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: "Internal server error during analysis",
|
||||
error: "Internal server error",
|
||||
details:
|
||||
process.env.NODE_ENV === "development" ? error.stack : undefined,
|
||||
},
|
||||
|
18
package-lock.json
generated
18
package-lock.json
generated
@ -29,6 +29,7 @@
|
||||
"node-fetch": "^3.3.2",
|
||||
"postcss": "^8.5.6",
|
||||
"puppeteer": "^24.11.2",
|
||||
"puppeteer-core": "^24.12.0",
|
||||
"react": "18.2.0",
|
||||
"react-curved-text": "^3.0.0",
|
||||
"react-dom": "18.2.0",
|
||||
@ -5149,6 +5150,23 @@
|
||||
}
|
||||
},
|
||||
"node_modules/puppeteer-core": {
|
||||
"version": "24.12.0",
|
||||
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.12.0.tgz",
|
||||
"integrity": "sha512-VrPXPho5Q90Ao86FwJVb+JeAF2Tf41wOTGg8k2SyQJePiJ6hJ5iujYpmP+bmhlb6o+J26bQYRDPOYXP7ALWcxQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@puppeteer/browsers": "2.10.5",
|
||||
"chromium-bidi": "5.1.0",
|
||||
"debug": "^4.4.1",
|
||||
"devtools-protocol": "0.0.1464554",
|
||||
"typed-query-selector": "^2.12.0",
|
||||
"ws": "^8.18.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/puppeteer/node_modules/puppeteer-core": {
|
||||
"version": "24.11.2",
|
||||
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.11.2.tgz",
|
||||
"integrity": "sha512-c49WifNb8hix+gQH17TldmD6TC/Md2HBaTJLHexIUq4sZvo2pyHY/Pp25qFQjibksBu/SJRYUY7JsoaepNbiRA==",
|
||||
|
@ -32,6 +32,7 @@
|
||||
"node-fetch": "^3.3.2",
|
||||
"postcss": "^8.5.6",
|
||||
"puppeteer": "^24.11.2",
|
||||
"puppeteer-core": "^24.12.0",
|
||||
"react": "18.2.0",
|
||||
"react-curved-text": "^3.0.0",
|
||||
"react-dom": "18.2.0",
|
||||
|
Loading…
x
Reference in New Issue
Block a user