* 这里以Vue.js开发方式进行举例
为什么要用混合渲染
在前面描述了CSR客户端渲染和SSR服务器端渲染两种方式。我们知道了:
- 如果想要做一个Vue主题,使用客户端渲染即可。
- 如果想被搜索引擎索引,使用服务器端渲染即可。
::: tip 那么问题来了:
我想要用Vue的方式去写主题,但是又希望被搜索引擎抓取,应该怎么办呢?
:::
混合渲染
基于上面的问题,nvPress开发者本人提供了 混合渲染(我自己随便起的名字)
的解决方案:
由于Vue是挂载到指定 Element 的,通常是 <div id="app">
,在挂载时,文件夹中的内容被完全由Vue覆盖。
于是我们知道:
浏览器: 支持Javascript,可以渲染到 #app
文件夹中并正常显示
搜索引擎: 不支持Javascript,无法渲染Vue内容
因此,只需要将服务器端渲染的内容放置到 <div id="app">
元素中。这样不支持JS的搜索引擎,可以看到标签中的内容进行抓取;支持JS的浏览器又可以渲染出正常的页面来覆盖专为搜索引擎提供的内容。
好比下面的样子:
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<script type="module" crossorigin="" src="/浏览器使用的JS.js"></script>
<link rel="stylesheet" href="/浏览器使用的CSS.css">
</head>
<body>
<div id="app">
<div>这里是给搜索引擎抓取的内容,vue渲染的时候会覆盖掉</div>
</div>
</body>
</html>
因此,在打包Vue主题时,生成的html文件只包含脚本和样式即可,别的标签全都丢弃:
vite.config.js
export default defineConfig({
build: {
rollupOptions: {
input: {
main: path.resolve(__dirname, 'application.html'),
},
//...
},
//...
},
//...
})
application.html
仅包含以下内容:
<script type="module" src="/src/main.js"></script>
这样打包出来的Vue项目中,application.html
就只包含脚本和样式了。在服务器端渲染时,把它的内容放置到 <head>
中就可以了。
主题 function.js
配置
nv_render_assistant({
// 服务器端渲染
rendering_mode: "SSR",
// 打包出来的在web目录,把它暴露出去,才可以直接访问到里面的样式和脚本文件
root_folder: get_theme_path("./dist/"),
// 由于Vue需要挂载到 #app 目录,在这里加上模板即可
template: {
head: (req,route_name) => `<!DOCTYPE html><html lang="zh-cn"><head>${ nv_head(req,route_name) }</head><body><div id="app">`,
foot: (req,route_name) => `</div></body></html>`,
},
// 服务器端渲染的路由,!!!要和Vue的路由匹配!!!
routes: [
{name: 'home', path: '/'},
{name: 'sitemap', path: '/sitemap.xml', type: 'text/xml'},
{name: 'articles', path: '/articles'},
{name: 'articles_paged', path: '/articles/page/:current_page'},
{name: 'post', path: '/:post_slug'},
{name: 'post_comment_paged',path: '/:post_slug/comment-page-:comment_page'},
{name: 'term', path: '/:taxonomy/:term_slug'},
{name: 'term_paged', path: '/:taxonomy/:term_slug/page/:current_page'},
{name: '404', path: '*', status: 404},
],
})
// 读取出打包后的Vue脚本和样式
var fs = require('fs');
var theme_scripts_and_styles = fs.readFileSync( get_theme_path("./web/application.html") ,{encoding:"utf8"} );
// 在head中把Vue打包的样式和脚本放进去
add_action('nv_head', ()=>{
nv_enqueue_head(theme_scripts_and_styles)
},99)
// 接下来就可以用钩子去渲染route内容了
// !!!由于只是给搜索引擎看,只需要渲染出最基础的标签即可!!!
add_action('async:nv_render:home',(next,{echo,req,route})=>{
echo(`<h1>欢迎访问首页</h1>`);
// 异步钩子,执行完后必须使用流程控制方法来执行下一个。
next();
})
示例主题
请前往 nvPress 后台的套件中心,下载“前后端混合渲染主题示例”