zoukankan      html  css  js  c++  java
  • 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

    虽然现在走得很慢,但不会一直这么慢
  • 相关阅读:
    Mongodb常用操作(转载)
    java中对象转换工具类,很好用
    IDEA中配置tomcat出现乱码的解决
    小山博客--面试题答案
    Redis简单配置和使用
    线程的控制和线程池
    进程与线程详细解释
    Quartz .Net(定时框架):
    C#面向对象几组关键字的详解(this,base,dynamic,var,const,readonly,is,as)
    C#设计模式--抽象工厂模式(创建型模式)
  • 原文地址:https://www.cnblogs.com/xxm980617/p/10753525.html
Copyright © 2011-2022 走看看