「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」
背景
vue是一个单页面的应用,这导致一些爬虫和百度无法搜索到。如果你想针对你应用的其中某些页面进行SEO优化,让他们可以被爬虫和百度搜索到,你可以进行预渲染操作,无需使用web服务器实时动态编译html,只需要在构建的时候简单的生成针对特定路由的静态html文件。优点是设置预渲染更简单,并可以将你得前端作为一个完全静态的站点。
ssr
要实现ssr,vue有一个文档Vue SSR 指南,大家可以去看看,里面讲的很详细,我在这里只简单地说一说。
问题一
为什么使用服务器端渲染 (SSR)?
1.更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面。
2.更快的内容到达时间 (time-to-content),特别是对于缓慢的网络情况或运行缓慢的设备。
......
还有好多优点
问题二
为什么要预渲染?
如果你调研服务器端渲染 (SSR) 只是用来改善少数营销页面(例如
/,/about,/demo等)的 SEO,那么你可能需要预渲染。无需使用 web 服务器实时动态编译 HTML,而是使用预渲染方式,在构建时 (build time) 简单地生成针对特定路由的静态 HTML 文件。优点是设置预渲染更简单,并可以将你的前端作为一个完全静态的站点。如果你使用 webpack,你可以使用 prerender-spa-plugin 轻松地添加预渲染。它已经被 Vue 应用程序广泛测试 - 事实上,作者是 Vue 核心团队的成员。
实现
创建 vue3.0 项目
使用 vuecli 可以很快的创建一个项目。大概如下:
多创建一个路由页面
在router/index.ts的文件中加入demo路由,如下:
import Demo from "../views/Demo.vue";
{
path: "/demo",
name: "Demo",
component: Demo,
},
创建demo页面
在views文件夹中创建Demo.vue文件,如下:
<template>
<div class="demo">
<h1>This is an demo page</h1>
</div>
</template>
引入prerender-spa-plugin
prerender-spa-plugin文档:
github: github.com/chrisvfritz…
有了文档我们执行下面代码:
npm install prerender-spa-plugin -D
效果如下:
修改 vue 配置
文档里有vue的demo,不过是vue2.0的,但是我们也可以看看:
1.新建vue.config.js文件
/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require("path");
const PrerenderSPAPlugin = require("prerender-spa-plugin");
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer;
module.exports = {
configureWebpack: {
plugins: [],
},
};
if (process.env.NODE_ENV === "production") {
module.exports.configureWebpack.plugins = (
module.exports.plugins || []
).concat([
new PrerenderSPAPlugin({
staticDir: path.join(__dirname, "dist"),
routes: ["/", "/about", "/demo"],
renderer: new Renderer({
inject: {
foo: "bar",
},
headless: true,
renderAfterDocumentEvent: "render-event",
}),
}),
]);
}
注意:
文件开始要加上:
/* eslint-disable @typescript-eslint/no-var-requires */,因为会报错,Require statement not part of import statement.,如下:
2.修改路由
要把router的mode改成history,也不要用懒加载模式
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
import Home from "../views/Home.vue";
import About from "../views/About.vue";
import Demo from "../views/Demo.vue";
const routes: Array<RouteRecordRaw> = [
{
path: "/home",
name: "Home",
component: Home,
},
{
path: "/about",
name: "About",
component: About,
},
{
path: "/demo",
name: "Demo",
component: Demo,
},
];
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes,
});
export default router;
3.修改App.vue
添加等待渲染,直到在文档上调度指定的事件。
import { defineComponent } from "vue";
export default defineComponent({
name: "App",
mounted() {
document.dispatchEvent(new Event("render-event"));
},
});
npm run build
看效果,demo和about文件夹里面都有index.html文件,说明我们成功了!!
思考
修改title
demo/index.html和about/index.html的title应该不一样,怎么修改? 答案1:
postProcess(context) {
var titles = {
"/": "Home",
"/about": "Our Story",
"/demo": "Demo",
};
context.html = context.html.replace(
/<title>[^<]*<\/title>/i,
"<title>" + titles[context.route] + "</title>"
);
return context;
},
答案2:
postProcessHtml: function (context) {
var titles = {
'/': 'Home',
'/about': 'Our Story',
'/demo': 'Contact Us'
}
return context.html.replace(
/<title>[^<]*</title>/i,
'<title>' + titles[context.route] + '</title>'
)
}
效果:
修改文件名和路径
怎么把demo和about文件夹的文件放到和index.html一层? 答案:
postProcess(renderedRoute) {
renderedRoute.route = renderedRoute.originalRoute;
renderedRoute.outputPath = path.join(
__dirname,
"dist",
(renderedRoute.route === "/" ? "home" : renderedRoute.route) + ".html"
);
return renderedRoute;
},
效果,如下: