SSR服务器端渲染

142 阅读2分钟

预渲染

什么时候使用预渲染

  • 只有少量页面需要SEO优化
  • 仅仅提高首屏的渲染速度,且首屏的几乎只有静态数据的情况

可以在构建时(build),简单地生成针对特定路由的静态HTML文件,把前端页面作为一个静态的站点,然后渲染出来,而不是使用服务器去把对应的html渲染到前端,要保证做单页面,第一次请求就能请求到SEO的页面。

在webpack中可以用prerender-span-plugin这个插件来实现预渲染,先下载这个插件

npm -i prerender-spa-plugin

需要在vue.config.js中进行对该插件的配置(更多配置项可以到npm官网上查看这个插件的使用方法说明)

// 引入插件
const PrerenderSPAPlugin = require('prerender-spa-plugin');
module.exports = {
    configureWebpack: config => {
    if (process.env.NODE_ENV !== 'production') return;
    return {
        plugins: [
            new PrerenderSPAPlugin({
                // 生成文件的路径,也可以与webpakc打包的一致。
                // 这个目录只能有一级,如果目录层次大于一级,在生成的时候不会有任何错误提示,在预渲染的时候只会卡着不动。
                staticDir: path.join(__dirname,'dist'),
                // 对应自己的路由文件,比如a有参数,就需要写成 /a/param1。
                // 如果只是渲染首页,可以使用hash路由,但是如果要渲染其他页面,则一定要将路由改为history模式。
                routes: ['/'],
                // 这个很重要,如果没有配置这段,也不会进行预编译。
                renderer: new Renderer({
                    inject: {
                        foo: 'bar'
                    },
                    // 是否开启无头浏览器,设置为false会在打包的时候看到浏览器弹出渲染路由。
                    headless: false,
                    // 注意要在 main.js 中 document.dispatchEvent(new Event('render-event')),两者的事件名称要对应上。
                    renderAfterDocumentEvent: 'render-event'
                })
            })
        ],
    };
  }
    
}

在入口文件index.js上也要配置

new Vue({
  router,
  store,
  render: h => h(App),
  mounted () {
    // 记得要与配置文件里的renderAfterDocumentEvent: 'render-event'对应上事件名。
    document.dispatchEvent(new Event('render-event'))
  }
}).$mount('#app')

服务端渲染

默认情况下,可以在浏览器中输出Vue组件,进行生成DOM和操作DOM,然而,也可以将同一个组件渲染为服务器端的HTML字符串,将它们直接发送到浏览器,最后将这些静态标记“激活”为客户端上完全可交互的应用程序。

image.png

如上图所示,vue组件在服务器端进行渲染,得到一个html,在这个html中已经包含了需要渲染出来的文字内容等等,那么在搜索引擎搜索拿html时,就可以查找到对应的文字,从而利于SEO

image.png 过程如上图所示,简单的实现和理解

简单实现代码

const express = require('express')()
const Vue = require('vue')
//创建服务端的渲染器
const renderer = require('vue-server-renderer').createRenderer()

//创建vue实例
const app = new Vue({
    template: '<div>hello world</div>'
})

//服务端渲染的核心在于:
//通过vue-servver-render插件的renderToString()方法,将vue实例转换成字符串插入到html文档中
express.get('/', (req, res) => {
    renderer.renderToString(app, (err, html) => {
        if (err) {return res.state(500).end('运行错误')}
        res.send(`
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>Document</title>
        </head>
        <body>
            ${html}
        </body>
    </html>
    `)
    })
})

express.listen(8881, ()=>{
    console.log('服务器已开启!')
})

image.png