VUE3项目SEO优化预渲染
如果你需要改善少数页面的seo,或者加快少数页面的打开时间。预渲染是个不错的选择。
预渲染相对于服务端 ssr 开发成本
更低,代码 侵入性
更低。
插件原理
在 npm run build
将代码打包成功以后,prerender-spa-plugin
插件会在指定目录开启一个服务,使用google开发的无头浏览器 puppeteer 模拟打开打包好的项目,爬取指定的预渲染页面,生成html文件。此时我们访问生成好的html页面就如同访问静态页面一样。
解决seo优化之预渲染prerender-spa-plugin
1,安装 prerender-spa-plugin
npm install --save prerender-spa-plugin
2,配置vue.config.js
// SEO 优化
const PrerenderSPAPlugin = require('prerender-spa-plugin');
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer;
const isProduction = process.env.NODE_ENV === 'production';
// 这里做二级目录部署
module.exports = {
...
productionSourceMap: false,
//资源拼接路径
process.env.NODE_ENV == "production" ? "/web/": "./"
// 打包后输出文件的目录
outputDir: process.env.NODE_ENV == "production" ? "dist/web/":"dist",
// outputDir的静态资源(js、css、img、fonts)目录
assetsDir: "static",
const plugins = [];
configureWebpack: config => {
if (isProduction) {
plugins.push(
new PrerenderSPAPlugin({
// 生成文件的路径,也可以与webpakc打包的一致。
// 下面这句话非常重要!!!
// 这个目录只能有一级,如果目录层次大于一级,在生成的时候不会有任何错误提示,在预渲染的时候只会卡着不动。
//staticDir: path.join(__dirname, process.env.VUE_APP_OUTPUT_DIR),如果直接用path 可能会报 错 不要问为什么我要特意备注一下
// 读取vue-cli已打包文件的根目录 prerender-spa-plugin会在这里开启一个服务
staticDir: path.join(__dirname,'dist'),
// 经过prerender-spa-plugin处理的文件最终保存的地方
outputDir: path.join(__dirname, '/dist/web/'),
// 指定入口html
indexPath: path.join(__dirname, 'dist/web/index.html'),
// 对应自己的路由文件,比如a有参数,就需要写成 /a/param1
routes: ['/','/index','/parcel','/warehouse','/artery','/scheme','/software','/port','/press','/hydt','/details','/map','/order','/issue','/job','/about','/company','/history','/cooperation','/contact','/404'],
// 这个很重要,如果没有配置这段,也不会进行预编译
renderer: new Renderer({
inject: {
foo: 'bar'
},
headless: false,
renderAfterDocumentEvent: 'render-event',
args: ['--no-sandbox', '--disable-setuid-sandbox']
})
}),
)
}
}
...
}
以上配置在 npm run build
后会打包到 dist/web/ 目录下,所有的静态资源会拼接上 /web/ 二级目录。prerender-spa-plugin 插件会读取 dist 目录,经过 prerender-spa-plugin 插件处理的文件也会覆盖放到 dist/web/ 目录下。
以上配置假定会部署到域名的根目录下。在部署时,直接将 dist 文件夹下的 vue 文件夹放到服务器的根目录下,通过 http://www.xxxxx.com/web/ 即可访问。
使用预渲染vue-router必须使用history模式(v4.x)
// vue-router 文件
import {
createRouter,
createWebHistory
} from 'vue-router'
const routes = [];
let base = process.env.NODE_ENV == "production" ?'/web/':'';
const router = createRouter({
history: createWebHistory(base),
routes,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return {
top: 0
}
}
}
})
App.vue 配置
<template>
<div></div>
</template>
<script>
import { defineComponent,onMounted } from 'vue';
export default defineComponent({
setup() {
onMounted(() => {
// 在这里添加 预渲染事件
document.dispatchEvent(new Event('render-event'))
})
return {}
}
})
</script>
<style lang='less' scoped>
</style>
main.js 配置
import {
createApp
import {
createApp
} from 'vue'
import App from './App.vue'
const app = createApp(App)
app.config.globalProperties.$SeoUpdate = (SeoTitle, SeoKeywords, SeoDescription) =>{
let _headDom = '',_title = '',_meta = '';
//获取head节点
_headDom = document.getElementsByTagName('head')[0];
//获取head节点下的title节点
_title = _headDom.getElementsByTagName("title")[0];
//获取head节点下的meta节点,它一般是一个数组
_meta = _headDom.getElementsByTagName("meta");
_title.innerText = SeoTitle;
for (let index = 0; index < _meta.length; index++) {
switch (_meta[index].name) {
case 'keywords':
_meta[index].content = SeoKeywords;
break;
case 'description':
_meta[index].content = SeoDescription;
break;
case 'searchtitle':
_meta[index].content = SeoDescription;
break;
default:
break;
}
}
console.log(SeoTitle, SeoKeywords, SeoDescription)
}
app.mount('#app')
在需要修改的页面使用,举例home.vue
<template>
<div></div>
</template>
<script>
import { defineComponent,getCurrentInstance,onMounted } from 'vue';
export default defineComponent({
setup() {
const { proxy } = getCurrentInstance();
onMounted(() => {
proxy.$SeoUpdate('seo标题','关键词1,关键词2,关键词3,关键词4,关键词5','网站描述--描述这个网站具体是围绕什么业务开展的')
});
return {}
}
})
</script>
<style lang='less' scoped>
</style>
执行 npm run build
执行构建编译 预编译生成的页面 可以看到设置的seo标题、描述、关键字等,举例如下图:
构建生成文件的目录结构,可以看出页面已经提前渲染出来了
打赏作者
微信
支付宝