其实SSR并不难,只是前端开发者不懂服务端开发而已。全栈工程师带你自己实现SSR

790 阅读4分钟

所以全栈估计很多人感觉是一个水货吧,但是我想说市面的全栈的确很多都不怎样。但是一个好的全栈是可以给出很多很好的解决方案。虽然全栈很少去看什么实现啊源码啊。但是全局思维和系统设计一个全栈的必修的课程。也就好像《java编程思想》和《JS高级编程设计》它们会带你学习V8引擎和范性是怎么实现的嘛?但是所有的开发提供的都是api和一种编码软件工程思路。你要学会思考这种问题,那是区分程序员和码农。要不你一样遇到很多编程(算法很牛的人)实现了很牛的功能,但是维护起来你想哭的局面。

与其一直卷下去,真的我就没见过那个国人写的软件可以想Spring Boot,React,AngularLaravel等等外国剧名框架每次升级的时候,都还能兼容老版本的。就连国内最好的PHP框架,thinkphp每次升级都带来不一样的用法...我们不应该卷底层,是时候卷的是设计和思维了吧。我希望大家不要在做生产线上的搬运工,而已多想想系统设计来简化自己的遇到问题。

回到正题这里用到的例子是React,服务端开发使用的是express。目前市面上的SSR渲染程序在React这方面拥有两个巨头Next.js和号称自己是最好的SSR框架的ssr-fc框架http://doc.ssr-fc.com。最新版本还兼容vite。

存在的问题。

两个框架都是别人的开发的,如你已经有一个spa的项目在运行了。这个时候呢公司给你的资源也就只有4-5个人要吧老项目迁移到上诉的两个框架中,由于开发的规范不是上诉所说的规范。这个时候迁移的成本其实是很大的!!!那这个时候为什么不自己去解决这个问题呢?而且不是所有项目的喜欢用ssr的。

客户端以服务器端渲染的区别

首先说说现在的客户端和服务器端的区别。React在这两个端中都充当模板引擎。只是一个是用来创建Create Dome,一个是服务端转译成html字符串。

目前的客户端执行过程可以简单的理解成以下过程

image.png

那什么是服务端渲染呢?

image.png

区别最明了的是你缺了一个服务端,哈哈哈废话文学开启。我这里使用比较特殊,不像其他友商使用koa,egg。如果你要定制做项目的话!请远离egg.js这种约束的框架。我没有选择koa是因为过于简单。这个时候我就要请出angular的大哥类似的nest.js同样使用express来做服务端。

这里有一个spa的项目,先看看工程结构。

image.png

//一个见的express服务
import express from 'express';

const app = express();

const port = 3000;
app.get('/', function (req, res) {
    res.send("hello,word");
})

app.listen(port, function () {
    console.log("run the server prot:", port);
})

image.png

image.png

我么要如何渲染React呢?这里我么有一个page的目录结构。可以进行相关渲染。

image.png

我么现在改改代码,让react做模板引擎。

import mouleAlias from 'module-alias';
import express from 'express';
import React from 'react';
import ReactDOM from 'react-dom/server';

mouleAlias.addAliases({
    "core": __dirname + "/../core/lingxi-cra/",
})

const app = express();
const port = 3000;

app.get('/', async function (req, res) {
    const Compoent = await (await import('./page/index')).default
    const html = ReactDOM.renderToString(<Compoent/>);
    await res.send(html)
})

app.listen(port, function () {
    console.log("run the server prot:", port);
})

image.png

效果如下,但是这个时候的点击效果你是无法操作的!!!renderToString不提供我们操作事件监听器的程式号,因此您如何点点无任何操作。

image.png

看到这些图,我们再次看到,SSR在后面有一小段,也就是要处理的次要。使用者看到内容的网页,只是HTML内容,然后需要将JS重新登录,然后通过React来设置和监听事件。

在你大概知道,我们还要有一个JavaScript档案用于事件后用户看到网页内容。这个时候也就有了CJS这样的一个说法ReactDOM.hydrate().

也就是大家平时的博主没有解释清楚为什么需要的替换ReactDOM.render()

编译一下

image.png

我们的的express进行修改一下。

const Compoent = await (await import('./page/index')).default

const context = ReactDOM.renderToString(<Compoent/>);


const html = `

<html>

<head></head>

<body>

<div id="root">${context}</div>

<script src="/js/main.87436269.js"></script>

</body>

</html>

`;

await res.send(html)

image.png

我这里没有做路由配置,只要原因是我打算做的是MVC框架,就算SPA我也是用Route制定的规范是和page做MVC的。

这些需要注意的是如果用了SSR的话,需要注意的是,你先spa做过的Router render都需要去除掉。如果你一开始就使用一个成IRouters进行抽象调用的话,其实改起来还是比较好改的。如果你不去掉的话会影响到服务端的路由。

当然也是有处理方案的,服务端使用StaticRouter。当时需要处理。如果阅读量不错的话,会出下一期SSR的Router篇