公司项目在已在开发完成的情况下通知需要做SEO优化。因为项目使用的是vue做的单页面应用,顿时人都不好了,只好网上搜罗出来一些配置(其实是另一个带我的老大哥他做的,但是他要走了,工作交接给我, 我需要掌握,所以也算是偷来一门技艺吧)。
交代一下:选用prerender-spa-plugin
插件配合vue-meta
前端全家桶敲代码前的规矩:配置好package.json
然后npm install
。或者
npm install --save prerender-spa-plugin vue-meta
但是不好意思,刚看了一眼之前写的注意事项,直接下载太慢了,首先还不能这样玩儿☺
安装插件的步骤分为两步:
1.首先添加环境变量,提高puppeteer的下载速度:PUPPETEER_DOWNLOAD_HOST=https://npm.taobao.org/mirrors
2.然后执行爽翻天的npm install操作
3.??还有3?install过程超级慢,先睡一觉吧!
不过倒是有个注意事项:下载过程中会下载一个无头浏览器(这就是下载慢的原因),一看无头浏览器就该知道SEO优化基本实现就靠它了吧。
要是下载失败,不好意思,请你把prerender相关的包删除掉再重新下载,直到下载成功!
prerender
相关文件:配置的时候要注意一点,配置时使用的
name
或path
,不是路由的name
或path
,应是真是确定的URL地址(访问浏览器时显示的真是URL)
prerender > config.js
exports.renderAfterDocumentEvent = '__PRERENDER_TRIGGER';
/**
* 需要预渲染的页面路由
* Note: 路由 url 不能超过两层
* @type { String[] }
**/
exports.routes = [
'/home/page', // ... 这里请配置路由 url
'/detail/1',
];
说明:
- 此处的路由真是地址栏的 url ,是什么样呢,就是我们这个用在详情页,然后把详情页的id写入了 url 中,结果就是
/detail/1
这样的配置。很无奈- 很重要的一点是,经过测试,这里配置的路由不能超过两层。我们之前也是有三层的,就是详情嘛,像
/page/detail/1
这样,但是不行,强行把路由改成了两级!
prerender > index.js
import Vue from 'vue';
const { renderAfterDocumentEvent } = require('./config');
const prerenderEvent = new Event(renderAfterDocumentEvent);
/** 通知开始保存预渲染页面 */
export const emitPrerender = (timeout = 0) =>
new Promise(resolve => {
Vue.nextTick(() => {
window.setTimeout(() => {
window.document.dispatchEvent(prerenderEvent);
resolve();
}, timout);
});
});
const { ContextReplacementPlugin } = require('webpack');
const PrerenderSPAPlugin = require('prerender-spa-plugin');
// 此处路径为prerender的配置路径
const PrerenderConfig = require('../src/prerender/config');
const simplifyMomentPlugin = new ContextPeplacementPlugin(/moment[/\\]locale$/, /zh-cn/);
// 渲染器(无头浏览器)配置项,使用 `renderAfterDocument` 来确定渲染时机
const renderer = new PrerenderSPAPlugin.PuppeteerRenderer({
// headless can be false when debug, 服务器上必须设置为true
headless: true,
renderAfterDocumentEvent: PrerenderConfig.renderAfterDocumentEvent,
defaultVireport: null,
});
const prerenderPlugin = new PrerenderSPAPlugin({
staticDir: resolve('dist'),
routes: PrerenderConfig.routes,
minify: {
minifyCSS: true,
removeComments: true,
keepClosingSlash: true,
caseSensitive: true,
},
renderer,
});
configureWebpack: config => {
config.plugins.push(simplifyMomentPlugin);
if (isProduction) config.plugins.push(prerenderPlugin);
}
emitPrerender
metaInfo
emitPrerender
: import { emitPrerender } from '@/prerender';
注:路径请自行脑补
// 如在 mounted 中页面赋值完成,执行
await emitPrerender();
注:拿产品详情页来说,一定要等到需要的数据渲染完成之后再执行函数。
metaInfo
:// 这里注意是一个新增的生命周期函数
metaInfo() {
return this.createMetaInfo();
}
// methods
createMetaInfo() {
const appTitle = '吕小胖纸的测试appTitle'; // 配置的项目名称
const siteURL = this.$app.siteURL; // 项目网址
const SITE_DESCRIPTION = '吕小胖纸的测试描述';
return {
title: appTitle,
meta: [
{ name: 'description', content: SITE_DESCRIPTION },
{ name: 'keywords', content: 'keywords' },
{ property: 'og:type', content: 'website'},
{ property: 'og:title', content: appTitle },
{ property: 'og:site_name', content: appTitle },
{ property: 'og:url', content: siteURL },
{ property: 'og:description', content: SITE_DESCRIPTION },
],
};
}
emmm,命名啊还有内容什么的别太在意了。
main.js
引用 import vueMeta from 'vue-meta';
vue.use(vueMeta);
运行npm run build
注:如遇到打包失败,报Puppeteer未安装等错误,需将已安装的包删除,或者尝试重启电脑再重新
npm install
等之后操作。
(emmmm,所以我上文是不是说错了,安装失败?打包失败?算了,反正都删掉再重新安装总是没错的)
路由模式改为hash模式:
// routes -> index.js new Router 加入属性
const router = new Router({
mode: 'history',
routes: [xxx],
});
修改打包后路径 vue.config.js
:
// 路由改为了hash模式,则vue.config.js中publicPath路径修改
publicPath : '/';
emmm,这里我就懒了,我的文件重定向了一下(皮一下),详见README.MD(主要寻找服务器配置参考)哈哈!
还是贴出来吧,也是记录大佬的文件!简洁。话说要不是我知道他肯定会整我,在他走之前把这个的配置流程过了一遍,我不得被他整死,给大家欣赏欣赏高冷风
README.md
emmm,话说直接插入md格式咋个搞(哭笑不得)那我就以js文本格式写吧
// ### 预渲染
为实现较完善的 SEO ,对部分页面进行渲染,使用 headless brower 渲染页面,保存生成后的静态 HTML 文件,便于搜索引擎爬取。
// #### 安装说明
* 添加环境变量,提高[`Puppeteer`](https://github.com/puppeteer/puppeteer)的下载速度
PUPPETEER_DOWNLOAD_HOST=https://npm.taobao.org/mirrors
* 若在服务器上打包,出现问题个查看[问题排查](https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md)
// #### 已知限制
* 路由需要使用 `history` 模式
* 需要预渲染的页面的 URL 不能超过两级(v3.4.0)
// #### 使用说明
1. 将需要预渲染的页面 URL 加入 `config.js` 的 `routes` 配置中
> 注意:不是路由的 `name` 或 `path`,应是真实确定的 URL 地址
2. 在页面组件中引入本模块的 `emitPrerender` 方法
```js
import { emitPrerender } from '@/prerender';
```
3. 在合适的时机(例如页面所有数据均已获取完成时),调用执行 `emitPrerender` 方法
老规矩,写文章是为了记录,毕竟以后可能会用到,另外,隔一段时间再回来看也是巩固知识啦!有任何不同声音探讨,我一定虚心请教其他人
完。