Vue项目预渲染机制

  我们知道SPA有很多优点,不过一个缺点就是对(不是Google的)愚蠢的搜索引擎的SEO不友好,为了照顾这些引擎,目前主要有两个方案:服务端渲染(Server Side Rendering)、预渲染(Prerending)。

  如果你只需要改善少数页面(例如 首页/, /about, /contact 等)的 SEO,那么你可能需要预渲染。无需使用 web 服务器实时动态编译 HTML (服务端渲染, SSR),而是使用预渲染方式,在构建时(build time)简单地生成针对特定路由的静态 HTML 文件。它主要使用 prerender-spa-plugin 插件,其与SSR一样都可以加快页面的加载速度,并且侵入性更小,在已上线的项目稍加改动也可以轻松引入预渲染机制,而SSR方案则需要将整个项目结构推翻。

  访问预渲染出来的页面在访问时与SSR一样快,并且它将服务端编译HTML的时机提前到了构建时,因此也降低了服务端的压力。不过SSR和预渲染的使用场景还是有较明显的区别的。

  预渲染的使用场景更多是简单的静态页面,对于那些大量的动态路由匹配(比如大量的文章详情,大量的活动详情等)就不适合了。服务端渲染适用于复杂、较大型、与服务端交互频繁的功能型网站,比如电商网站。

1、安装

  安装跟其他库一样:npm install prerender-spa-plugin --save-dev

2、前端配置

(1)router/index.js的配置,预渲染要求是histroy模式,有的文章说不需要history模式,这是错的,否则生成的页面都是同一个html。

  另外注意加上base,否则如果你希望跳转到二级页面的localhost/base/home时候,在页面中点击<router-link to="/home">home</router-link>的时候会跳转localhost/home

import Vue from 'vue'
import Router from 'vue-router'
 
Vue.use(Router)
 
export default new Router({
  mode: 'history',
  base: '/base/',
  routes: [...]
})

(2)然后是config,这里注意assetsPublicPath不是./,

// config/index.js
const path = require("path")
module.exports = {
  build: {
    index: path.resolve(__dirname, "../base/index.html"),
    assetsRoot: path.resolve(__dirname, ".."),
    assetsSubDirectory: "base/static",
    assetsPublicPath: "/",
  }
}

(3)然后是插件的配置,是放在prod中的,因为只有build的时候会用

// build/webpack.prod.conf.js

const path = require('path')
const config = require('../config')
const PrerenderSPAPlugin = require('prerender-spa-plugin')
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer
 
const webpackConfig = merge(baseWebpackConfig, {
  new PrerenderSPAPlugin({
   staticDir: config.build.assetsRoot,
   outputDir: path.join(config.build.assetsRoot, 'base'),
   indexPath: config.build.index,
 
   // 对应路由文件的path
   routes: [
     '/',
     '/BigData',
     '/CompanyHonor'
   ],
 
   renderer: new Renderer({
     headless: false,            // 无桌面系统去掉
     renderAfterDocumentEvent: 'render-event'
   })
  })
})

  注意了,如果你的项目是部署在linux/centOS之类没有桌面的系统,需要把headless: false去掉,如果centOS报没有找到lib的错,请参考 issue-200 的解决办法。

  另外注意上面一个renderAfterDocumentEvent: 'render-event'了么,这个意思是在render-event事件触发之后执行prerender,这个事件我们在main.js中mounted钩子触发

import Vue from 'vue'
import App from './App'
 
new Vue({
  el: '#app',
  render: h => h(App),
  mounted() {
    document.dispatchEvent(new Event('render-event'))
  }
})

  这时候执行npm run build就可以生成刚刚配置在PrerenderSPAPlugin插件中routes中的页面html了,这过程中会一闪而过的短暂打开chromium浏览器,不用管。最后生成的目录树:

│  index.html
├─BigData
│      index.html
├─CompanyHonor
│      index.html
└─static
    ├─css
    ├─fonts
    ├─img
    └─js

  最后如果希望进一步优化生成出来页面的SEO,可以配合 vue-meta 使用,动态设置title、keywords等。

posted @ 2019-08-19 23:11  古兰精  阅读(4150)  评论(0编辑  收藏  举报