vue项目做seo(prerender-spa-plugin预渲染)
对于vue、react、angular这类项目而言,seo真的是一大痛点。为什么seo是spa项目的痛点网络爬虫在爬取网页内容的时候,需要分析页面内容,主要有以下几点:从meta标签中读取keywords、description的内容。根据语义化的html的标签爬取和分析内容。一个整体都是用div标签的网站和正确使用了html5标签的效果是不一样的。读取...
对于vue、react、angular这类项目而言,seo真的是一大痛点。
为什么seo是spa项目的痛点
网络爬虫在爬取网页内容的时候,需要分析页面内容,主要有以下几点:
- 从
meta
标签中读取keywords
、description
的内容。 - 根据语义化的
html
的标签爬取和分析内容。一个整体都是用div
标签的网站和正确使用了html5
标签的效果是不一样的。 - 读取
a
标签里的链接,通过a
标签的链接可以跳转到别的网站。(爬虫是先跳转,还是继续爬内容再跳转,就看算法是广度优先还是深度优先了) - 像
h1 - h6
标签是具有不同程度的强调意义的。 一般将h1
视为重要内容。同样有强调内容还有strong
、em
标签。
爬虫在爬取的过程中,不会去执行js,所以隐藏在js中的跳转也不会获取到。
spa正好就踩到了痛点,只有一个主要的页面(index.html),而且页面里的内容还很少,通常只有 router-view
或者带有 id
的 div
标签。其跳转和业务逻辑的行为都是靠执行js才行的。
据说google已经支持爬取spa。
技术栈
vue v2.0
+ vue-router
+ vuex
+ webpack v3.6
+ prerender-spa-plugin v3.2.1
+ vue-meta-info
+ vue-cli v2
具体步骤
使用 npm
或 yarn
安装 prerender-spa-plugin
和 vue-meta-info
的过程就不描述了。
在webpack中配置 prerender-spa-plugin
配置先弄懂要配置在哪个文件里,配置是否生效。 vue-cli2
的配置文件很多,对这些文件不了解的话,很容易配置错地方。
这个配置只需要在 build
的时候可以生成预渲染好的html,所以应该配置在 build/webpack.prod.conf.js
这个文件里。
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const baseWebpackConfig = require('./webpack.base.conf')
const PrerenderSPAPlugin = require('prerender-spa-plugin')
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer
const webpackConfig = merge(baseWebpackConfig, {
plugins: [
// vue-cli生成的配置中就已有这个了,不要动
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunksSortMode: 'dependency'
}),
// 在vue-cli生成的文件的基础上,只有下面这个才是我们要配置的
new PrerenderSPAPlugin({
// 生成文件的路径,也可以与webpakc打包的一致。
// 下面这句话非常重要!!!
// 这个目录只能有一级,如果目录层次大于一级,在生成的时候不会有任何错误提示,在预渲染的时候只会卡着不动。
staticDir: path.join(__dirname, '../dist'),
// 对应自己的路由文件,比如index有参数,就需要写成 /index/param1。
routes: ['/', '/index', '/skin', '/slimming', '/exercise', '/alPay', '/wxPay'],
// 这个很重要,如果没有配置这段,也不会进行预编译
renderer: new Renderer({
inject: {
foo: 'bar'
},
headless: false,
// 在 main.js 中 document.dispatchEvent(new Event('render-event')),两者的事件名称要对应上。
renderAfterDocumentEvent: 'render-event'
})
})
]
})
在 webpack.prod.conf.js
配置完成之后,然后再 main.js
里改成如下所示:
new Vue({
el: '#app',
router,
store,
render: h => h(App),
/* 这句非常重要,否则预渲染将不会启动 */
mounted () {
document.dispatchEvent(new Event('render-event'))
}
})
如果将上面两个地方配置好了,离成功也就近了。然后运行一下 npm run build
。看一下生成的 dist
的目录里是不是有每个路由名称对应的文件夹。然后找个 目录里 的 index.html
用IDE打开,看文件内容里是否有该文件应该有的内容。有的话,这步就成功了。
在vue中使用 vue-meta-info
vue-meta-info
的使用相对就简单多了,就是vue的一个组件而已。 在 main.js
中写上
import MetaInfo from 'vue-meta-info'
Vue.use(MetaInfo)
在 xxx.vue
文件里写上以下代码。这些代码会转换成网页的 meta
标签里的内容。
export default {
metaInfo: {
title: '我是一个title',
meta: [
{
name: 'keywords',
content: '关键字1,关键字2,关键字3'
},
{
name: 'description',
content: '这是一段网页的描述'
}
]
}
}
下面是踩的坑
-
这里使用的
prerender-spa-plugin
的版本是3.2.1
,在2.x
的版本中有个写法如下var PrerenderSpaPlugin = require('prerender-spa-plugin') const webpackConfig = merge(baseWebpackConfig, { plugins: { //配置 prerender-spa-plugin new PrerenderSpaPlugin( // 生成文件的路径,此处与webpack打包地址一致 path.join(config.build.assetsRoot), //config.build.assetsRoot为vue cli生成的配置,打包后的文件地址 // 配置要做预渲染的路由,只支持h5 history方式 [ '/', '/test'] ) } })
以上
2.x
的写法,在3.x
的版本会提示一个警告,让你采用对象的形式 -
网上也有些说法,让预渲染方式下的 route 采用
history
模式,经过试验,没有必要!没有必要!没有必要!(真香)。留言中的大佬说的很好,实验了一下,确实还是得采用history模式,否则每个index.html文件的内容都会是一样的。route 的
history
模式就是如下代码中配置export default new Router({ mode: 'history', routes: [ // ... ] })
history
模式下的route,将不会以hash
的形式展示,也就是说,URL里没有#
了。 -
配置写错了文件,一开始一直写在了
/config/index.js
这个文件里。一启动,没效果。再启动,还是没效果。直到我冷静下来,喝了一口水,思考了一下人生,想了一想,这里是10楼,每层楼高3.5米,重力加速度是9.8,地面是水泥的,撞击地面的时候会发生轻微的弹性形变,然后享年24岁。经过一系列的思想斗争,我觉得,肯定是我的配置压根就没有被运行。然后我被我的机智折服了。打开
package.json
文件,看了看npm run build
指令时执行的js文件的顺序,发现了惊天的秘密。原来
/config
目录下的文件,只是给webpack的配置项提供值而已。真正配置webpack插件应该在/build
下配置。因为是要在
npm run build
的时候生成那些html,所以应该配置在webpack.prod.conf.js
文件里。 -
一个习惯引起的坑,在打包的过程中,习惯将
html
和resources
分开成两个文件夹。一直没想到,多了一层html
会导致prerender-spa-plugin
插件卡在预渲染(自动打开一个Chrome,开始编译)。 -
用了
vue-cli
构建的项目,在配置之后然后开心的npm run build
时,满心期待,心情愉悦的等待中。发现,诶,不成功!好气,很气,非常气!而且啊,没有任何错误提示,没有任何错误提示,没有任何错误提示。
然后就这么点东西,花了我三天的时间
其他SPA的SEO方案
除了预渲染,当然还有别的解决方案。实质上方案只有两种,预渲染就是使用的 phantomjs
先运行的。
- 采用ssr(服务端渲染)
- phantomjs
vue项目提供了ssr的方案,还有集成ssr方案的 nuxt.js
可以使用。不过ssr方案需要在node上调用 renderToString
来渲染。如果不介意在系统结构中增加一层 node
的话,就可以使用ssr的方式,这种方式会改变前后端交互的方式。
总结
总结还是一条一条来吧
-
不要以为会搬运代码,就可以当程序员了,得会思考。在发现有问题的时候,先停下尝试的手,把已经可以确定的东西分析清。找到产生问题的原因。就比如第一个坑,找到的很多代码都是采用的非对象的写法,在这个写法里,
main.js
里也不需要加上那句mounted() {// ...}
。这个时候首先应该想到版本是不是会影响配置文件的写法。发生问题的时候,确认一下自己的方向是否正确。从发现配置写在
webpack.prod.conf.js
的时候,已经是第三天了。方向对了之后,花了半天就找到了剩下的问题所在。 -
代码的心思要多猜,在你看不懂源码,没有那个时间成本去了解深层原理的时候,你需要猜。猜测引起这个问题的原因,但是不要瞎猜。这里就猜测了版本带来的差异,猜测了配置文件没有起作用,猜测了文件夹目录会引起问题。
-
学会尝试。预渲染这个确实是文档描述的不够仔细,每个属性的说明只有简单的两句描述。网上的例子,大多和自己的环境不匹配。用
vue-cli
的肯定用的2.x
的prerender-spa-plugin
。没用vue-cli
的,配置文件都和自己不一样。只有去尝试更多例子,然后确定哪部分配置才是有效的。
最后,如果这篇文章有说明不仔细或者有纰漏的地方,可以留言告诉我。
更多推荐
所有评论(0)