Vue(服务端渲染)

 

一、前言                                                                    

                                                1、服务端渲染图解

                                                2、简介服务端渲染

                                                3、vue-cli脚手架项目创建,实现客户端渲染和服务端渲染

                                                4、演示demo地址:https://github.com/4561231/ssr-vue

 

二、主要内容                                                             

1、服务端渲染图解参照另一篇:服务端渲染和客户端渲染

 

2、简介服务端渲染

Vue.js是构建客户端应用程序的框架,默认情况下,可以在浏览器中输出vue组件,进行生成Dom和操作DOM, 然而,也可以将同一个组件渲染成为服务端的字符串,将他们直接发送到浏览器,最后将这些静态标记“激活”为客户端上完全可以交互的应用程序。也就是你先在前端写好组件页面,然后交到服务端,服务端需要通过他自家的某个程序插件,然后将客户端的组件生成对应的html字符串,最后发送给浏览器。然后浏览器响应出来页面。

 

3、 新建项目,安装依赖路,创建服务端代码

  (1)server.js

const Vue = require('vue')
const express = require('express')();

const renderer = require('vue-server-renderer').createRenderer();

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

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

express.listen(8888, ()=>{
    console.log('服务器已经启动')
})

 

 

  (2)具体实现原理

  (3)测试,发现响应回来的文件里面有内容,这样也说明了服务端渲染是对SEO引擎比较好的

 

   (4)小结:我们使用服务端渲染是为了弥补单页面应用SEO能力不足的问题,实际上我们第一次在浏览器地址栏输入地址的时候,并且得到返回页面之后,所有的操作仍然是单页面应用在控制的,我们所做的服务端渲染,只是在平时返回单页面应用hml上增加了对应路由的页面信息,让爬虫好爬取到。

所以项目可以分为客户端渲染和服务端渲染。

 

4、用vue-cli项目实现服务端渲染

  (1)npm创建项目

  (2)npm run build的时候打包走的是webpack.prod.config.js这个文件,现在我们新建一个webpack.server.config.js这个文件,在服务器打包的时候走这个文件

  package.json里面加入如下代码

"server":"webpack --config build/webpack.server.conf.js"

       webapck.server.config.js添加如下代码

//引入webpack的主要配置
const webpack = require('webpack')
const merge = require('webpack-merge')

//引入webpack.base.config这个文件是依赖这个基础文件的
const base = require('./webpack.base.config')

module.exports=merge(base, {
    target:'node',//这里要写node 目的是让后端支持require语法
    entry:"./src/entry-server.js",//当你服务端在打包的时候,就会走这个入口
    output:{
        filename:'bundle.server.js',//打包后生成的文件
        libraryTarget:'commonjs2'
    },
    plugins:[]
})

  (2)由于以前生成vue实例的方式是单例的,现在我们需要在每次请求的时候生成一个vue组件

  在mian.js中修改


/*
eslint-disable no-new */ //El:’#app相当于document.getElementbyId(‘#app’ 但是在node.js中识别不了这种语法,所以我们不能这样写 /*new Vue({ el: '#app', router, components: { App }, template: '<App/>' })*/ import {createRouter} from './router' export function createApp(){
const router = createRouter(); const app
= new Vue({ router, components:{App}, template:'<App/>' })
return {app}; }

  同理最好将路由也写成构造函数形式

export default createrRouter(){
  return new Router({
    mode:'history',
    routes:[
    {
      path:'/',
      name:'Home',
      component:Home
    },
    {
      path:'/about',
      name:'About',
      component:About
    },

    {
      path:'/test',
      name:'Test',
      component:Test
    }

    ]
  })

  (3)npm run server打包生成文件,并在服务端引入客户端生成的打包文件

      打包生成文件

            

  在服务端引入打包生成的文件

//需要在服务端配置打包生成的客户端文件
const createApp = require('./dist/bundle.server.js')['default']

   (4)服务端拿到客户端打包生成的文件,进行处理

const Vue = require('vue')
const express = require('express')();
//需要在服务端配置打包生成的客户端文件
const createApp = require('./dist/bundle.server.js')['default']
const renderer = require('vue-server-renderer').createRenderer();
//服务器渲染的核心就在于:
//通过vue-server-renderer插件的renderToString()方法,将vue实例转化为字符串插入到html中
express.get('*',(req,res)=>{
    const context = {url:req.url};
    createApp(context).then(app=>{//这个app就是刚刚打包之后的app
          renderer.renderToString(app, (err,html)=>{
        if(err){
            return res.state(500).end('运行错误')
        }
          //返回给浏览器一串html字符串
        res.send(`<!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>服务端渲染</title>
        </head>
        <body>
            ${html}
        </body>
        </html>`)
    })
    })//取到entry.js里面的
})

express.listen(8888, ()=>{
    console.log('服务器已经启动')
})

 

   (5)测试看到一开始请求的时候就会出现内容,可以看到服务器返回的html文件中,已经有对应页面的SEO信息了。

 

 

 

  

 

          但是,还没有成功,因为现在反回过来的只是一个页面对应信息,如果你现在切换路由又会对服务器发送一次请求,单页面应用还没成功。但是vue的特点就是利用单页面,

 

接下来需要配置客户端渲染

  (1)在package.json中配

 "client": "webpack --config build/webpack.client.conf.js"

  (2)新建webpack.client.conf.js

const webpack = require('webpack')
const path = require('path')

function resolve(dir){
  return path.join(__dirname,'..',dir)
}

module.exports={
  entry:"./src/entry-client.js",//打包时走这个文件
  output:{
    path:path.resolve(__dirname,'../dist'),
    publicPath:'/dist/',
    filename:'bundle.client.js'
  },

  plugins:[],

  resolve:{
    extensions:['.js','.vue','.json'],
    alias:{
      'vue$':'vue/dist/vue.esm.js',
      '@':resolve('src'),
    }
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          compilerOptions:{
            preserveWhitespace:false
          }
        }

      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
      }
    ]
  }
}

  (3)entry-client.js

//客户端也要创建,因为客户端渲染和服务端渲染是两个不同的vue实例
import{createApp} from './main'

const {app} =createApp();
const router =app.$router;

//这里可以拿到app了,
window.onload=function(){
    app.$mount('#app')//在window加载完成之后
}

  (4)npm run client打包生成文件

  (5)同样需要在服务器中添加打包的客户端文件

//客户端渲染文件
const exp = require('express');
///将静态文件目录设置为:项目根目录+/dist
express.use('/',exp.static(__dirname+'/dist'));
//客户端打包的文件
const clientBundleFileUrl = '/bundle.client.js'
//在下面的模板中用script的方式引入
<script src="${clientBundleFileUrl}"></script>

  (6)启动服务器,测试

4、总结:

            (1)要做ssr服务端渲染首先需要一个Sever entry他的作用是渲染SEO的信息

            (2)如果你仅仅只有这四步操作,并没有实现单页面应用,而是每次点击的时候都会对服务端发起请求

 

       

 

   (3)要实现单页面应用,需要做客户端打包,然后将客户端打包的文件混入到服务端

  (4)单页面应用,只有第一次加载的时候才会发送请求,点击a标签的时候加载的是组件,

 

 5、

 

 

三、总结                                                                    

https://ssr.vuejs.org/zh/guide/structure.html#介绍构建步骤

https://segmentfault.com/a/1190000015964813

posted @ 2019-04-23 18:06  mysunshine_SZZ  阅读(2236)  评论(0编辑  收藏  举报