spa应用seo优化方案(arm服务器)
最近公司需要对网页进行seo优化,奈何项目为vue的spa应用,没那么方便改造,所以记录一下优化经历一、非SSR项目进行seo优化有以下四种方案:二、文件编写ssr文件:const puppeteer = require('puppeteer');const Cacheman = require('cacheman');const md5 = require('md5');let browserW
最近公司需要对网页进行seo优化,奈何项目为vue的spa应用,没那么方便改造,所以记录一下优化经历
目录
一、非SSR项目进行seo优化有以下五种方案:
-
ssr服务端渲染:项目所使用的的微前端框架需要使用window对象,无法实现
-
使用puppeteer,slimerjs搭建nodejs服务,通过nginx判断请求头是否为爬虫,是则指向通过puppeteer拉取html并返回html的地址,否则指向正常页面
-
通过php或jsp开发简易网站,只包含需要进行seo优化的内容的,通过nginx判断请求头是否为爬虫,是则指向seo页面,否则指向正常页面
-
预渲染,只能生成静态文件,对于有动态加载数据的页面不支持,不采用
-
nuxt,和ssr方案一样,不适合
所以将采用puppeteer这种方案
二、文件编写
ssr文件:
const puppeteer = require('puppeteer');
const Cacheman = require('cacheman');
const md5 = require('md5');
let browserWSEndpoint = null;
const FilecCache = new Cacheman('htmls', {
// 缓存3个小时
ttl: 60 * 60 * 3,
engine: 'file',
});
async function ssr (url) {
let browser = null;
let urlMd5 = md5(url);
// 是否命中缓存
var hitByCache = await FilecCache.get(urlMd5);
if (hitByCache) {
console.log(hitByCache)
return hitByCache;
}
if (browserWSEndpoint) {
try {
browser = await puppeteer.connect({browserWSEndpoint});
} catch (e) {
browserWSEndpoint = null;
browser = null;
}
}
if (!browserWSEndpoint) {
browser = await puppeteer.launch({
headless: true,
ignoreHTTPSErrors: true,
args: [
// Required for Docker version of Puppeteer
'--no-sandbox',
'--disable-setuid-sandbox',
]
});
browserWSEndpoint = await browser.wsEndpoint();
}
const start = Date.now();
const page = await browser.newPage();
// 1. 监听网络请求
await page.setRequestInterception(true);
page.on('request', req => {
// 2. 忽略不必要的请求,如图片,视频样式等等
const whitelist = ['document', 'script', 'xhr', 'fetch'];
if (!whitelist.includes(req.resourceType())) {
return req.abort();
}
// 3. 其它请求正常继续
req.continue();
});
try {
// networkidle0 等待直到500ms内没有请求了
await page.goto(url, {waitUntil: 'networkidle0'});
} catch (err) {
console.error(err);
throw new Error('page.goto/waitForSelector timed out.');
}
const html = await page.content(); // 获取HTML结构
// 写入缓存
await FilecCache.set(urlMd5, html.results);
await browser.close();
const ttRenderMs = Date.now() - start;
console.info(`Headless rendered page in: ${ttRenderMs}ms`);
return {html, ttRenderMs};
}
module.exports = {ssr}
server.js文件:
var express = require('express');
var {createProxyMiddleware} = require('http-proxy-middleware');
var app = express();
var server = require('http').createServer(app);
var history = require('connect-history-api-fallback');
var {ssr} = require('./ssr.js');
var listenPort = 3000;
// const proxy = {
// '/static/assets': {
// target: 'https://www.ccyunchina.com',
// changeOrigin: true
// },
// };
//
// for (let key in proxy) {
// app.use(key, createProxyMiddleware(proxy[key]));
// }
const staticFileMiddleware = express.static('dist');
app.use(function (req, res, next) {
var UA = req.headers['user-agent'];
var isStaticDir = false;
// 判断是否是爬虫, 排除资源目录的请求
if (UA && !isStaticDir) {
// 生成本地访问链接
var requestUrl = req.protocol + '://' + req.hostname + req.originalUrl;
(async () => {
try {
var results = await ssr(requestUrl);
res.send(results.html);
} catch (e) {
console.log('ssr failed', e);
res.status(500).send('Server error');
}
})();
return;
}
next();
});
// 先
app.use(staticFileMiddleware);
// 如果资源没命中会继续、经过history rewirte后
app.use(history({
disableDotRule: true,
verbose: true
}));
// 再次处理
app.use(staticFileMiddleware);
server.listen(listenPort, function () {
console.log('Spider app listening on port 3000!');
});
三、arm环境中nodejs环境搭建
uname -a
查看服务器是否是64位的- 64位的安装v8版本,32位的安装v7版本
wget https://npm.taobao.org/mirrors/node/v14.9.0/node-v14.9.0-linux-arm64.tar.xz
- 下载下来后运行
xz -d /usr/local/node-v14.10.0-linux-arm64.xz
和tar -xvf /usr/local/node-v14.10.0-linux-arm64.tar
进行解压和编译 - 修改 ~/.bashrc。在文末加入一句
export PATH=/usr/local/node-v14.10.0-linux-arm64/bin:$PATH
改变环境变量或网上的文章是用软链接的方式,将bin文件的node、npm加入的原本的环境变量的文件夹里面去 node -v
测试一下
四、arm环境下安装谷歌或火狐浏览器
注意puppeteer是使用的谷歌内核,如果要使用火狐内核,需要改用puppeteer-firefox,参考链接
yum -y install firefox
火狐安装
谷歌arm64版本可以参考网址下载(https://fedora.pkgs.org/32/fedora-aarch64/chromium-80.0.3987.163-1.fc32.aarch64.rpm.html)
五、nginx配置
设置map
map $http_user_agent $is_bot {
default 0;
~*bot 1;
~*spider 1;
'Yahoo! Slurp China' 1;
'Mediapartners-Google' 1;
'YisouSpider' 1;
}
修改location
location / {
error_page 418 =200 @bots;
if ($is_bot) {
return 418;
}
add_header Cache-Control no-store;
root dist/;
index index.html;
#proxy_pass http://127.0.0.1:3000;
try_files $uri $uri/ /index.html;
}
location @bots {
rewrite ^/(.*) http://$server_name:3000 permanent;
}
这里自己的爬虫服务用nodejs启动的是3000端口
六、用pm2管理nodejs服务
pm2得到使用可以参考这边文章https://www.jianshu.com/p/e15fd72727fe
七、专门针对seo生成网页
可以使用beetle搭建一个简陋的网页,页面只返回需要给爬虫爬取的数据,不需要任何样式或逻辑,通过第五步设置的nginx转发在配置相同的路由即可
更多推荐
所有评论(0)