当前位置: 首页 > Web前端 > HTML

本篇文章带你了解SSR

时间:2023-03-28 13:36:55 HTML

想多说多说,可是秋凉了----《丑奴儿·书博山道中壁》辛弃疾什么是SSRShadowsocksR?阴阳师?FGO?服务器端呈现(SSR)是应用程序通过在服务器上显示网页而不是在浏览器中呈现网页来呈现网页的能力。服务器向客户端发送一个完全呈现的页面(准确地说只是HTML)。同时结合客户端JavaScriptbundle,页面可以运行。与SSR不同的是,还有一个客户端渲染(CSR)。CSR和SSR最大的区别只是渲染是由客户端提供还是服务端提供,本质上还有另外一回事。因此,如果下面没有突出显示CSR和SSR之间的差异,则它们默认是一致的。为什么要使用SSR得益于React等前端框架的发展,前后端分离,webpack等编译工具的流行,以及ajax实现的页面局部刷新,我们现在的应用没有不再需要像以前的应用程序那样从服务器下载。获取页面后,可以动态修改部分页面数据,避免页面频繁跳转等问题影响用户体验。即SPA越来越成为主流的应用模型。但是使用SPA,除了上面提到的优点之外,也难免会带来缺点。例如:由于在页面加载前需要加载所有页面所需的JavaScript库,所以第一次打开页面需要很长时间;需要开发专门针对SPA的web框架(各种具有SSR能力的框架,包括Next.js等)搜索引擎爬虫浏览器历史记录(各种基于pushState的路由器)为了解决上述1.和3问题,SSR开始走上历史舞台。如何做SSR基于以上理论,我们可以设计一个具有SSR功能的React框架。首先我们通过create-react-app命令初始化一个React项目,初始化后的项目可以理解为一个功能最简单的项目。我们将基于这个项目实现一个SSR功能。#yarn$yarncreatereact-appssr-demo??同学们在练习的时候需要注意,当前版本的cra命令创建新项目的时候,会报类似Mini....isnotafunction的问题。这是mini-css-extract-plugin插件版本更新导致的。只需要通过package.json中的解析将mini-css-extract-plugin的版本限制为2.4.5即可生成项目目录如下:./├──README.md├──build├──node_modules├──package.json├──public├──src└──yarn.lock已经自动安装依赖,我们可以在“本地环境”启动项目到最简单的页面。接下来我们来实现一个SSR函数。首先,我们需要安装express(如果是CSR,则不需要这一步)yarnaddexpress安装完成后,我们需要在server/index.js文件中写入如下代码importexpressfrom"express";importserverRendererfrom"./serverRenderer.js";constPORT=3000;constpath=require("path");constapp=express();constrouter=express.Router();//当爬虫请求过来的时候在,将所有请求定向到serverRendererroutingrouter.use("*",serverRenderer);app.use(router);app.listen(PORT,()=>console.log(`listeningon:${PORT}`));其中serverRenderer文件内容如下:importReactfrom"react";importReactDOMServerfrom"react-dom/server";importAppfrom"../src/App";constpath=require("path");constfs=require("fs");exportdefault(req,res,next)=>{//获取当前项目的HTML模板文件路径constfilePath=path.resolve(__dirname,"..","build","index.html");//读取文件fs.readFile(filePath,"utf8",(err,htmlData)=>{if(err){console.err或(“错误”,错误);返回res.status(404).end();}//将JSX渲染成HTML字符串consthtml=ReactDOMServer.renderToString();//将HTML字符串替换为根returnres.send(htmlData.replace('

',`${html}
`));});};如上,我们已经完成了一个非常简单的带有SSR功能的服务器,但是这还不够,我们还需要在根目录下新建一个parser.js,将ESM转换成CommonJS才能运行起来,代码如下:("ignore-styles");require("@babel/register")({忽略:[/(node_modules)/],预设:["@babel/preset-env","@babel/preset-react"],});要求(“。/服务器”);解释一下上面介绍的包的作用:@babel/register:这个依赖会在后面运行的时候需要node需要进来的扩展。es6、.es、.jsx、.mjs和.js的文件将由Babel自动转译。ignore-styles:该依赖也是一个Babelhook,主要用于Babel编译时忽略样式文件的导入。经过以上操作,我们首先yarn构建我们的产品,然后通过nodeparser.js启动SSR服务。经过以上操作,我们就设计出了一个非常简单但合理的SSR服务器。为了对比,我们这里简单的和Next.js对比一下。在Next.js项目根目录下的package.json中,我们可以看到服务器也选择了express..."eslint-plugin-react-hooks":"4.2.0","execa":"2.0.3","express":"4.17.0","faker":"5.5.3",...我们可以在~/packages/next/server/next.ts文件夹A中找到Next.jsNextServer对象会通过createServer方法启动,负责启动服务器和渲染模板模板。命令调用如下:在[Next.js]官网(https://nextjs.org/docs/basic-features/pages#server-side-rendering)中可以看到支持getServerSideProps函数在页面上实现接口数据的动态获取。事实上,大多数支持SSR的框架库中都有类似的设计。因为SPA的应用,不可避免的要通过服务端获取动态数据并渲染页面,而SSR渲染动态数据的设计思路是比较一致的。即在页面的组件所在的同一个文件中导出一个固定的方法,返回一个固定的格式。该框架将使用此数据作为页面SSR渲染的初始数据。下面我们以Next.js为例,了解一下SSR的总体设计思路,接下来我们来了解一下CSR的总体思路。CSR可以理解为SSR的阉割版,只实现了SSR的预渲染功能。一般用于静态网站,不具备动态获取数据的功能。CSR的渲染思路和SSR是一样的,不同的是SSR需要安装express而CSR不需要安装express。这也导致了CSR和SSR在部署流程上的差异。Next.js应用等SSR项目在执行build命令后可以运行start命令启动服务器,不再需要配合nginx的反向代理。而Umi这样的CSR项目还是需要nginx代理的。CSR最大的不同在于编译产品的不同。通常,一个前端项目的编译产物包括:bundle.js或chunk.jsindex.htmlindex.csspublic/*其他相关文件,如rss.xml等。带CSR的项目编译后,会有更多HTML文件,这些文件的架构将根据路由生成。例如:我们现在的路由是这样的:/a/b分别对应ComponentA和ComponentB,那么在我们的编译产物中就会生成a.html和b.html。我们将产品部署到nginx服务后,就可以实现预渲染功能了。实现以上功能,最重要的步骤如下:获取当前项目的路由,并获取路由对应的组件。如果组件尚未编译,则需要编译。利用react-dom的能力将JSX渲染成HTML,插入到模板HTML中,在编译后的产品中根据路由创建文件夹,将生成的HTML生成到相应的路径中。至此,我们就了解了SSR的整个流程,相信大家对SSR也有了一定的了解。现在社区的大部分框架都不需要我们自己做SSR。我们对渲染过程的理解有助于我们在处理无穷无尽的框架时保持一致。