vuecli3改ssr,验证你的ssr是否成功

3,201 阅读4分钟

概述

文章主要是抄的别人的,主要是作为记录。

先放大佬的文章地址:

通过vue-cli3构建一个SSR应用程序

基于vue-cli3 SSR 程序实现热更新功能

怎么说呢,个人对于ssr有点执念。首先,我们知道ssr其实就是以前早期的mvc时代的M部分,也就是模板开发的那会。但是到了前后端分离的时代,ssr变成了一个较为复杂的东西。主要是因为现在的ssr因为react,vue等框架,是自带模板作用。如果直接在服务端使用是无法使用的。

然后我在去年的时候就自己反复的自建过ssr,像nuxt,eggjs自家提供的esaywebpack等都有尝试。但是自己经常会想,如果是公司最核心的项目需要用ssr,是应该自建还是用nuxt这样的框架。

而nuxt这样的框架有一个致命点,我们需要pm2这样的工具来保证多线程的性能使用。我在早先的时候使用eggjs,就不需要pm2。并且eggjs支持多线程启动,经历了双十一。所以我非常想把ssr和eggjs合并在一起。但是我还是想自己实现。

多次翻看官方ssr文档:ssr.vuejs.org/zh/,每次都是在we…

最终就抄来这片文章了。

流程

这块我不想概述了,主要就是抄的大佬的。上述作者的流程完整的走下来完全是可以的。

主要是两个坑点

1、关于koa-router部分的星号路由产生的报错

router.get("*", handleRequest);

我改为了了/

2、vue.config改造的时候启动的时候报错,

optimization这个是没有的,加上之后不会报错

optimization: {
	      splitChunks: TARGET_NODE ? false : undefined,
	    },
	    plugins: [TARGET_NODE ? new VueSSRServerPlugin() : new VueSSRClientPlugin()],

3、个人改造之后的git地址:github.com/ht-sauce/vu…

如何验证自己改造成功呢?

看着大佬的改造成功跑起来之后呢自己其实有点方,不知道到底是否成功。

先讲一下关于百度等搜索引擎原理。其实核心原理就是一个爬虫程序会去请求你的地址,然后获取到你内部的html页面,最后根据html页面进行分析得到你的内容。

那spa为什么获取不到。给个例子:

<!DOCTYPE html>
<html lang=en>
<head>
    <meta charset=utf-8>
    <meta http-equiv=X-UA-Compatible content="IE=edge">
    <meta name=viewport content="width=device-width,initial-scale=1">
    <link rel=icon href=/dve/favicon.ico>
    <link rel=stylesheet type=text/css href=/dve/element-ui/2.13.0/index.css>
    <script src=/dve/vue/2.6.11/vue.min.js></script>
    <script src=/dve/element-ui/2.13.0/index.js></script>
    <script src=/dve/vuex/3.0.1/vuex.js></script>
    <script src=/dve/wavesurfer/wavesurfer.js></script>
    <title>数字人视频编辑器</title>
    <link href=/dve/css/digital.6f1b1310.css rel=prefetch>
    <link href=/dve/js/digital.90f990ef.js rel=prefetch>
    <link href=/dve/css/app.4434a726.css rel=preload as=style>
    <link href=/dve/js/app.1936d768.js rel=preload as=script>
    <link href=/dve/js/chunk-vendors.919914d8.js rel=preload as=script>
    <link href=/dve/css/app.4434a726.css rel=stylesheet>
</head>
<body>
<noscript><strong>请允许浏览器执行JavaScript</strong></noscript>
<div id=app></div>
<script src=/dve/js/chunk-vendors.919914d8.js></script>
<script src=/dve/js/app.1936d768.js></script>
</body>
</html>

如上你在搜索引擎下得到的内容就是这样的。那能得到个锤子哦。

而搜索引擎要得到的内容是比如csdn这样的

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <link rel="canonical" href="https://blog.csdn.net/liumiaocn/article/details/108267949"/>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <meta name="renderer" content="webkit"/>
    <meta name="force-rendering" content="webkit"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="report" content='{"pid": "blog", "spm":"1001.2101"}'>

            <meta name="applicable-device" content="pc">
        <meta http-equiv="Cache-Control" content="no-siteapp" />

    <meta name="referrer" content="always">
    <link rel="alternate" media="handheld" href="#" />
    <meta name="shenma-site-verification" content="5a59773ab8077d4a62bf469ab966a63b_1497598848">
            <meta name="csdn-baidu-search"  content='{"autorun":true,"install":true,"keyword":"云IDE:Eclipse Che:Eclipse下一代IDE"}'>

    <link href="https://csdnimg.cn/public/favicon.ico" rel="SHORTCUT ICON">
    <title>云IDE:Eclipse Che:Eclipse下一代IDE_知行合一 止于至善-CSDN博客</title>
        <meta name="keywords" content="云IDE:Eclipse Che:Eclipse下一代IDE">
        <meta name="description" content="Eclipse Che被Eclipse官方称为下一代IDE,作为老牌的IDE,被其寄予厚望的Eclipse Che到底有什么特点,在这篇文章中我们来一探究竟。">
    <script src='//g.csdnimg.cn/tingyun/1.8.3/blog.js' type='text/javascript'></script>

                    <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/new_css/detail_enter-54d3fd4be5.min.css">
                            <script type="application/ld+json">{"@context":"https:\/\/ziyuan.baidu.com\/contexts\/cambrian.jsonld","@id":"https:\/\/blog.csdn.net\/liumiaocn\/article\/details\/108267949","appid":1638831770136827,"title":"\u4e91IDE\uff1aEclipse Che\uff1aEclipse\u4e0b\u4e00\u4ee3IDE_\u77e5\u884c\u5408\u4e00 \u6b62\u4e8e\u81f3\u5584-CSDN\u535a\u5ba2","pubDate":"2020-08-28T07:48:16","upDate":"2020-08-28T07:48:16"}</script>

            <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/themes_skin/skin-number/skin-number-01fe94d91c.min.css">

<!--    自定义皮肤样式-->
    <script src="https://csdnimg.cn/public/common/libs/jquery/jquery-1.9.1.min.js" type="text/javascript"></script>
    <!--js引用-->
            <script src="//g.csdnimg.cn/??fixed-sidebar/1.1.6/fixed-sidebar.js,report/1.5.6/report.js" type="text/javascript"></script>
    <link rel="stylesheet" href="https://csdnimg.cn/public/sandalstrap/1.4/css/sandalstrap.min.css">
    <style>
        .MathJax, .MathJax_Message, .MathJax_Preview{
            display: none
        }
    </style>
</head>
<body class="nodata " > 
    <link rel="stylesheet" href="https://csdnimg.cn/public/common/toolbar/content_toolbar_css/content_toolbar.css">
    <script id="toolbar-tpl-scriptId" src="https://csdnimg.cn/public/common/toolbar/js/content_toolbar.js" type="text/javascript" domain="https://blog.csdn.net/"></script>
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/new_css/blog_code-c3a0c33d5c.css">
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/vendor/pagination/paging-e040f0c7c8.css">

<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/new_css/chart-3456820cac.css" />
<div class="main_father clearfix d-flex justify-content-center" style="height:100%;"> 
    <div class="container clearfix" id="mainBox">
        <aside class="blog_container_aside">
	<!--主页引入-->

    <div id="asideProfile" class="aside-box">
    <div class="profile-intro d-flex">
        <div class="avatar-box d-flex justify-content-center flex-column">
            <a href="https://blog.csdn.net/liumiaocn"  data-report-click='{"mod":"popu_379","spm":"1001.2101.3001.4121","dest":"https://blog.csdn.net/liumiaocn","ab":"new"}'>
                <img src="https://profile.csdnimg.cn/5/1/1/3_liumiaocn" class="avatar_pic" username='liumiaocn'>
            </a>
        </div>
        <div class="user-info d-flex flex-column profile-intro-name-box">
            <div>
                                <a href="https://blog.csdn.net/liumiaocn" class="" id="uid" title='淼叔' data-report-click='{"mod":"popu_379","spm":"1001.2101.3001.4122","dest":"https://blog.csdn.net/liumiaocn","ab":"new"}' >
                    <span class="name " username='liumiaocn'>
                        淼叔                    </span>
                </a>
                <span></span>
                <span class="flag expert-blog"><img class="identity" src="https://csdnimg.cn/identity/expert.png" alt=""><span class="bubble">CSDN认证博客专家</span></span>
                <span class="flag company-blog"><span class="bubble">CSDN认证企业博客</span></span>
            </div>

            <div class="profile-intro-name-boxFooter">
                                    <span class="personal-home-page">码龄4年</span>
                                            <span class="personal-home-page"><a class="personal-home-certification" href="https://me.csdn.net/liumiaocn?utm_source=14998968" target="_blank"><img src="https://csdnimg.cn/identity/nocErtification.png" alt="">暂无认证</a></span>
                                                </div>
        </div>
    </div>

大致是这个样子的,可以看到你的html内容里面是带有除了head头部之外的还有html标签等内容。

注意这是一次请求,不是你先像上面先请求页面路径,然后通过js再渲染页面的。记住,这是第一次请求的时候服务器给浏览器的内容

给个最简单的爬虫,自己试试

这个其实就很简单的,其实大家也可以用普通的ajax请求来试试。只要你请求到的内容是第一次就带有html标签等关键信息的,那么就是成功了。

下面是express部分的代码

安装其实就是

npm i express superagent cheerio

SuperAgent,用于服务端请求地址数据的

cheerio 就是一个最小jQuery,但是他可以在服务端使用

const express = require('express');
// 调用 express 实例,它是一个函数,不带参数调用时,会返回一个 express 实例,将这个变量赋予 app 变量。
const superagent = require('superagent');
const cheerio = require('cheerio');
const app = express();

app.get('/', (req, res, next) => {
  superagent.get('http://localhost:3000')
    .end((err, sres) => {
      // 常规的错误处理
      if (err) {
        return next(err);
      }
      // sres.text 里面存储着网页的 html 内容,将它传给 cheerio.load 之后
      // 就可以得到一个实现了 jquery 接口的变量,我们习惯性地将它命名为 `$`
      // 剩下就都是 jquery 的内容了
      let $ = cheerio.load(sres.text);
      let items = sres.text;
      console.log(sres.text)
      /*$('.item_title a').each((idx, element) => {
        let $element = $(element);
        items.push({
          title: $element.text(),
          href: $element.attr('href')
        });
      });*/

      res.send(items);
    });
});

app.listen(5000, function () {
  console.log('app is listening at port 5000');
});

最后

最后没啥,主要是表达下自己这次的文章比较潦草。