由於之前曾經有過一個專案需求。
客戶原本使用的是很單純的PHP+HTML的專案。
所以其使用者體驗很差。每一個換頁都會先白頁一下。(畢竟是請求的方式)
所以協助幫其使用了 VUE 元件的展示方式。
雖然使用者體驗變好了。但伴隨來的就是SEO不會讀取的問題。
於是,我用了AI及網路上的支援。簡單配合一下寫了一支臨時的SSR對應處理
先附上程式碼 index.js
將上面的程式碼先放好一個位置。
再來就是開始準備工作了。
要用之前,要先準備好幾個事前工作
如果需要背景運行,可以搭配 pm2 來處理。
不過一開始先確定一下是否運行成功。
不過這邊要先注意,由於這是後處理的方式。所以如果是直接應用到實際的專案上,會變得很慢。
所以我這裏還會搭配一些 WEB SERVER 。
只有 SEO 相關的連結進來才會跑SSR。(畢竟它慢沒關係)
這邊我就直接給 NGINX 的設定
先在 HTTP 區塊中給與如下設定
這是先給一個變數,用來判斷是否要觸發處理
再來就是到對應需要觸發的位置給判斷
以上很簡單的就是,利用了 user_agent 來判斷是否包含了(GTM|Googlebot|Bingbot) 這些值。
如果包含了就直接給與 proxy 到 http://localhost:3000
這邊的指向,你可在啟動SSR伺服器看到。只要跟它一樣就行。
這樣子處理是不是很方便呢?
當然啦。這只能簡單性的處理。如果碰上切頁等資料的。還是不會取到。
但至少是能應付大半問題了
客戶原本使用的是很單純的PHP+HTML的專案。
所以其使用者體驗很差。每一個換頁都會先白頁一下。(畢竟是請求的方式)
所以協助幫其使用了 VUE 元件的展示方式。
雖然使用者體驗變好了。但伴隨來的就是SEO不會讀取的問題。
於是,我用了AI及網路上的支援。簡單配合一下寫了一支臨時的SSR對應處理
先附上程式碼 index.js
JavaScript:
const express = require('express');
const { Cluster } = require('puppeteer-cluster');
const app = express();
const PORT = process.env.PORT || 3000;
(async () => {
// 创建一个 Puppeteer Cluster
const cluster = await Cluster.launch({
concurrency: Cluster.CONCURRENCY_CONTEXT,
maxConcurrency: 2, // 根据服务器性能调整此值
puppeteerOptions: {
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox']
}
});
// 任务处理函数
cluster.task(async ({ page, data: { url, acceptLanguage } }) => {
await page.setExtraHTTPHeaders({ 'Accept-Language': acceptLanguage });
await page.goto(url, { waitUntil: 'networkidle0' });
return await page.content();
});
app.get('*', async (req, res) => {
// 动态设置 Puppeteer 访问的 URL
const protocol = req.headers['x-forwarded-proto'] || req.protocol;
const host = req.headers['host'];
const url = `${protocol}://${host}${req.originalUrl}`;
const acceptLanguage = req.headers['accept-language'] || '';
try {
console.log(`Rendering URL: ${url} with Accept-Language: ${acceptLanguage}`);
// 执行 Puppeteer Cluster 任务,传递 url 和 acceptLanguage
const html = await cluster.execute({ url, acceptLanguage });
res.send(html);
} catch (error) {
console.error('Error during SSR with Puppeteer:', error);
res.status(500).send('An error occurred while rendering the page.');
}
});
app.listen(PORT, () => {
console.log(`SSR server is running on http://localhost:${PORT}`);
});
// 在进程终止时关闭集群
process.on('SIGINT', async () => {
await cluster.idle();
await cluster.close();
process.exit();
});
})();
將上面的程式碼先放好一個位置。
再來就是開始準備工作了。
要用之前,要先準備好幾個事前工作
- 安裝無頭瀏覽器
-
豐富的(BB 代碼):
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.debsudo apt install ./google-chrome-stable_current_amd64.deb
- 因為會需要用到它來處理頁面的回傳。
-
- 事前掛入好套件及建好環境
- 先進行初始化處理 yarn init -y
- 再來掛入套件 yarn add express puppeteer
如果需要背景運行,可以搭配 pm2 來處理。
不過一開始先確定一下是否運行成功。
不過這邊要先注意,由於這是後處理的方式。所以如果是直接應用到實際的專案上,會變得很慢。
所以我這裏還會搭配一些 WEB SERVER 。
只有 SEO 相關的連結進來才會跑SSR。(畢竟它慢沒關係)
這邊我就直接給 NGINX 的設定
先在 HTTP 區塊中給與如下設定
NGINX:
map $http_user_agent $proxy_pass_enabled {
default 0;
~*(GTM|Googlebot|Bingbot) 1;
}
再來就是到對應需要觸發的位置給判斷
NGINX:
location / {
#這裏判斷要觸發SSR伺服器用,用剛剛給的變數判斷
if ($proxy_pass_enabled) {
proxy_pass http://localhost:3000;
}
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 以下是原來的設定
try_files $uri $uri/ /index.html;
}
以上很簡單的就是,利用了 user_agent 來判斷是否包含了(GTM|Googlebot|Bingbot) 這些值。
如果包含了就直接給與 proxy 到 http://localhost:3000
這邊的指向,你可在啟動SSR伺服器看到。只要跟它一樣就行。
這樣子處理是不是很方便呢?
當然啦。這只能簡單性的處理。如果碰上切頁等資料的。還是不會取到。
但至少是能應付大半問題了