最近公司需要对网页进行seo优化,奈何项目为vue的spa应用,没那么方便改造,所以记录一下优化经历
目录
- 一、非SSR项目进行seo优化有以下五种方案:
- 二、文件编写
- 三、arm环境中nodejs环境搭建
- 四、arm环境下安装谷歌或火狐浏览器
- 五、nginx配置
- 六、用pm2管理nodejs服务
- 七、专门针对seo生成网页
一、非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转发在配置相同的路由即可