This commit is contained in:
黄心宇 2023-09-27 12:38:28 +08:00
parent c2a86a0d65
commit 642f057bbd
8 changed files with 2531 additions and 1 deletions

9
.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
/node_modules
/.env.local
/.umirc.local.ts
/config/config.local.ts
/src/.umi
/src/.umi-production
/src/.umi-test
/dist
.swc

View File

@ -1,2 +1,31 @@
# PupTester
# SeoServer
#### node版本
16及以上
#### ng配置
```
if ($http_user_agent ~* "googlebot|Mediapartners-Google|bingbot|google-structured-data-testing-tool|baiduspider|360Spider|Sogou Spider|Yahoo! Slurp China|^$")
{#判断如果是网络爬虫转发到node服务器下
proxy_pass http://www.test.com:3000;
break;
}
```
#### 依赖安装、运行
```bash
// 依赖
npm install
npm install pm2 -g
node node_modules/puppeteer/install.js // 安装无头浏览器可能会缺依赖可参见https://www.cnblogs.com/ilizhu/p/14504049.html
// 启动服务
pm2 start index.js
```
#### 配置
config中修改redis地址端口、node服务端口、以及转发host

5
config.js Normal file
View File

@ -0,0 +1,5 @@
export const redis = 'redis://127.0.0.1:6379';
export const host = 'https://www.gitlink.org.cn';
// export const host = 'http://119.3.190.9:8000';
export const port = 3000;

32
index.js Normal file
View File

@ -0,0 +1,32 @@
import request from 'request';
import express from 'express';
import ssr from './ssr.js';
import { port, host } from './config.js';
const app = express()
// app.get('/api/*', async (req, res) => {
// request(`${host}${req.url}`).pipe(res);
// });
// app.get('/react/build/*', async (req, res) => {
// request(`${host}${req.url}`).pipe(res);
// });
// app.get('/images/*', async (req, res) => {
// request(`${host}${req.url}`).pipe(res);
// });
// app.get('/system/lets/*', async (req, res) => {
// request(`${host}${req.url}`).pipe(res);
// });
app.get('*', async (req, res) => {
const {html, ttRenderMs} = await ssr(`${host}${req.originalUrl}`);
res.set('Server-Timing', `Prerender;dur=${ttRenderMs};desc="Headless render time (ms)"`);
return res.status(200).send(html); // Serve prerendered page as response.
});
app.listen(port, () => {
console.log(`app listening on port ${port}`)
})

2370
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

19
package.json Normal file
View File

@ -0,0 +1,19 @@
{
"name": "seotest",
"version": "1.0.0",
"description": "seotest",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"bluebird": "^3.7.2",
"express": "^4.18.2",
"puppeteer": "^21.2.0",
"redis": "^4.6.8",
"request": "^2.88.2"
},
"type": "module"
}

24
redis/index.js Normal file
View File

@ -0,0 +1,24 @@
import { createClient } from 'redis';
import { redis as url } from '../config.js';
const client = createClient({
url: url,
retry_strategy: function(options) {
if (options.error && options.error.code === "ECONNREFUSED") {
return new Error("The server refused the connection");
}
if (options.total_retry_time > 1000 * 60 * 60) {
return new Error("Retry time exhausted");
}
if (options.attempt > 10) {
return undefined;
}
return Math.min(options.attempt * 100, 3000);
},
});
client.on('error', err => console.log('Redis Client Error', err));
await client.connect();
export default client

42
ssr.js Normal file
View File

@ -0,0 +1,42 @@
import puppeteer from 'puppeteer';
// import redisClient from './redis/index.js';
async function ssr(url) {
// const REDIS_KEY = `ssr:${url}`;
// const CACHE_TIME = 600; // 10 分钟缓存
// const CACHE_HTML = await redisClient.get(REDIS_KEY);
// if (CACHE_HTML) {
// return { html: CACHE_HTML, ttRenderMs: 0 };
// }
const start = Date.now();
const browser = await puppeteer.launch({
args: ['--no-sandbox', '--disable-setuid-sandbox'],
headless: 'new',
ignoreHTTPSErrors: true,
devtools: false,
});
const page = await browser.newPage();
try {
// networkidle0 waits for the network to be idle (no requests for 500ms).
await page.goto(url, {waitUntil: 'networkidle0'});
await page.waitForSelector('#root', { timeout: 0 }); // ensure #posts exists in the DOM.
} catch (err) {
console.error(err);
throw new Error('page.goto/waitForSelector timed out.');
}
const html = await page.content(); // serialized HTML of page DOM.
await browser.close();
const ttRenderMs = Date.now() - start;
console.info(`Puppeteer rendered page: ${url} in: ${ttRenderMs}ms`);
// redisClient.set(REDIS_KEY, html, 'EX', CACHE_TIME); // cache rendered page.
return {html, ttRenderMs};
}
export {ssr as default};