前端渲染模式

渲染的概念

        在Web开发中,渲染(Rendering)是一个核心概念,指的是将应用程序的数据(data)与模板(template)结合,生成最终的HTML页面,这个页面随后会被浏览器解析并展示给用户。这个过程是动态Web应用的核心,因为它允许开发者根据不同的数据动态地生成页面内容,而不是每次更改都需要手动编写静态的HTML文件。

        我们可以简单地把渲染理解为:渲染就是将页面数据和页面模版组装成html的过程

也就是: data + template = html,当然data也可能什么都没有,没有数据也是一种数据

  • 客户端渲染就是 data + template = html 过程在客户端进行,服务器直接转发静态 html 资源即可

  • 服务端渲染就是 data + template = html 过程在服务端进行,客户端不需要渲染页面

  • 静态化渲染就是打包的时候进行 data + template = html 过程,然后客户端在请求时,服务端不做任何处理,直接以原文件的形式返回给客户端,客户端获取到页面后,在加载完 JS 后才通过 JS 来渲染页面内容。

单页应用和多页应用

  • 单页应用:

    • 只有一个页面,可以部分更新,通过vue 的diff对比树结构的不同而部分更新,点击跳转新页面并不产生新的html,所以跳转时缓存不会消失,不需要把数据存在本地里面

  • 多页应用:

    • 有多个页面,每一次跳转都会生成新的html,整棵树都会重新构建,而不是部分更新,state一刷新就没了,所以就经常要把数据存在localstorage、sessionstorage、cookie里面

    多页面应用(MPA)单页面应用(SPA)
    组成一个外壳页面和多个页面片段组成多个完整页面构成(但外观看起来只有一个页面)
    资源共用不共用,每个页面都需要加载CSS和JS共用,只需在外壳部分加载CSS和JS
    刷新方式整页刷新页面局部刷新或更改
    URL模式a.com/pageone.html, a.com/pagetwo.htmla.com/#/pageone, a.com/#/pagetwo 等(Hash模式)或 a.com/pageone, a.com/pagetwo(History模式,需要服务器支持)
    用户体验页面切换加载缓慢,流畅度不够页面片段间的切换快,用户体验良好
    转场动画容易实现容易实现(但SPA通常提供更好的转场效果)
    数据传递依赖URL传参、cookie、localStorage等容易,可以通过 JavaScript 在内存中直接传递
    搜索引擎优化(SEO)较差,需要服务器端渲染(SSR)优化实现方法较为困难,不利于SEO检索(但可通过预渲染等技术改善)
    适用范围适用于追求高度支持搜索引擎的应用高要求的体验度、追求界面流畅的应用
    开发成本较低,但页面重复代码多较高,常需借助专业的框架和库
    维护成本相对复杂相对容易(一旦架构搭建好,后续维护较为简单)

页面的渲染流程

1、浏览器通过请求得到一个HTML文本

2、渲染进程解析HTML文本,构建DOM树

3、解析HTML的同时,如果遇到内联样式或者样式脚本,则下载并构建样式规则(stytle rules),若遇到JavaScript脚本,则会下载执行脚本

4、DOM树和样式规则构建完成之后,渲染进程将两者合并成渲染树(render tree)

5、渲染进程开始对渲染树进行布局,生成布局树(layout tree)

6、渲染进程对布局树进行绘制,生成绘制记录

7、渲染进程对布局树进行分层,分别栅格化每一层,并得到合成帧

8、渲染进程将合成帧信息发送给GPU进程显示到页面中

渲染模式分类

  • CSR:Client Side Rendering,客户端(通常是浏览器)渲染

  • SSR:Server Side Rendering,服务端渲染

  • SSG:Static Site Generation,静态网站生成

  • ISR:Incremental Site Rendering,增量式的网站渲染

  • DPR:Distributed Persistent Rendering,分布式的持续渲染

从 CSR 到 SSR

CSR客户端渲染

        当用户访问某个URL时,服务端返回的HTML是不包含页面具体内容的骨架,然后由客户端的JavaScript来完成页面的渲染

        对于使用Vue或者React构建的单页面web应用,当我们打开浏览器访问页面时服务器一般只会返回一个比较简单的html模版,之后浏览器再加载相应的js并进行解析,生成dom元素将页面渲染出来。

        普通的单页应用只有一个 HTML,在浏览器请求页面时,服务端只会生成一个无具体内容的 html 文件,之后都是浏览器通过加载并执行 chunk.js 这种 JavaScript 去动态更新,所以无法被爬虫识别,不利于SEO。

        这种渲染方式虽然在后续的页面切换速度很快,但是也明显存在两个问题:纯客户端的 SPA 在首屏加载SEO 方面有显著的问题,因为浏览器会收到一个巨大的 HTML 空页面,只有等到 JavaScript 加载完毕才会渲染出内容,白屏时间过长且 SEO 不友好。

        优点:

1、响应速度快:一旦HTML文件加载完成,浏览器就可以开始渲染页面,而不需要等待服务器返回完整的渲染结果

2、动态性强:页面渲染在客户端进行,因此可以方便地实现更好的交互性和动态效果

3、前端部署简单:只需要一个静态服务即可部署前端代码,降低了部署成本

4、减轻服务端的压力,因为大部分渲染工作都在客户端完成

        缺点:

1、首屏加载慢:需要等待 JavaScript 下载和执行,可能导致首屏加载时间较长,特别是对于复杂的单页应用(SPA)

2、不利于SEO:有些搜索引擎爬虫无法执行 JavaScript,看不到完整的程序源码,获取不到页面关键信息

3、白屏时间:在JavaScript代码加载和执行期间,用户可能会看到空白的页面,即所谓的“白屏时间”

SSR 最早是为了解决单页应用SPA产生的 SEO、首屏渲染时间等问题而诞生的。

SSR服务端渲染

        当用户访问某个URL时,服务端实时生成包含内容的HTML文件,返回给浏览器解析后能直接构建出有内容的页面。

        页面html先在服务端渲染完成,此刻得到的一堆的html字符串,返回给浏览器后便可直接进行解析渲染,完成后用户便可看到完整的页面,大大减少了白屏时间,之后再加载js,使网页可进行正常交互。

        在服务端直接实时同构渲染用户看到的页面,整个查数据库的过程以及 html 都由服务端生成,客户端只需要识别返回的一大堆 html 代码。能让服务器直接返回渲染好的 HTML,让用户在 JavaScript 下载完毕前就看到页面内容,提高用户使用体验。

        这种渲染方式需要一个服务器承载页面的实时请求、渲染和响应,增大了服务端的开发和运维的成本。对于一些较为静态场景,比如博客、官网等,它们的内容相对确定,变化不频繁,每次请求都会重新生成页面,且每次通过服务端渲染出来的内容都是一样的,浪费了很多没必要的服务器资源

        优点:

1、首屏加载速度快:服务器已经生成了完整的HTML页面,可以生成缓存片段,因此客户端可以直接显示这个页面,无需等待JavaScript加载和执行

2、SEO友好:搜索引擎爬虫可以直接看到渲染好的 HTML,有利于SEO优化

3、适合复杂页面:对于包含大量数据、需要复杂计算的页面,SSR可以更好地处理并减少客户端的负载

        缺点:

1、服务端压力大:对于每个请求,服务器都需要重新渲染页面,这可能导致服务器压力过大,可以用静态化来解决

2、无法交互:SSR 是直接产出 HTML 的代码,DOM 元素事件绑定的逻辑仍然需要 JS 才能够完成,因此页面不可以交互

        解决方案:SSR页面引入CSR的脚本(同构)。在实际场景中,会在SSR页面中加入CSR的脚本,完成DOM的事件绑定,这个完成事件绑定的过程,也被称为 Hydration。

3、传统服务端渲染的用户体验较差、不容易维护,通常前端改了部分 html 或者 css,后端也需要修改

4、开发调试困难:开发要考虑到服务器端和客户端环境的差异,调试要考虑到服务器端和客户端的日志和错误信息

从 SSR 到 SSG

        SSG在构建的过程当中,也就是当执行 npm build 时,就可以生成完整的HTML内容,构建完成后进行HTML部署,在生产环境下就不需要服务器的开发、运维相关的工作,研发和运维的成本会比SSR低一些

SSG静态页面生成

        在构建时预先渲染页面并生成静态的 HTML,把生成的HTML静态资源部署到服务器后,用户访问某个URL时,服务端直接返回包含页面内容的HTML即可。

        在项目构建时生成包含内容的html,之后将相应的html、js、css等静态资源发布到相应的CDN节点,这样当用户进行访问时页面可直接渲染。

        服务端会预加载,先把所有 html 页面都生成好并放到CDN上,在客户端需要的时候直接返回,不需要服务器实时渲染和响应,大大节约了服务器运维成本和资源,比 SSR 少了一个去数据库CRUD的操作,效率更高,SEO友好,但是只适合页面内容较为静态的场景,比如官网、博客等,因为服务端渲染可以提前完成。

        但它对服务器的要求很高,因为如果有成千上万个页面,它就要预先生成成千上万个模板,需要耗费很多服务器资源。难以应对高度动态的内容或页面数量很多的情况,因为在静态构建时不能拿到最新的数据,也无法枚举海量页面。

        优点:

1、性能卓越:页面是静态的,因此无需等待服务器渲染,直接由浏览器加载显示,具有极快的页面加载速度

2、安全性高:服务器只提供静态文件,因此降低了遭受攻击的风险

3、服务器压力小,减轻服务端的渲染压力,继承了SSR首屏性能以及优秀的SEO支持

4、适合内容型网站:对于数据变化频率较低的内容型网站(如博客、文档网站等),SSG是一个很好的选择

        缺点:

1、动态性受限:页面是静态的,因此难以实现复杂的动态交互效果,不适用于数据经常变化的场景

2、构建时间长:对于频繁更新数据的大型网站不太适合,因为需要重新构建和部署整个网站,构建时间可能会比较长

3、不适合频繁更新:对于需要频繁更新数据的网站,SSG可能不太适合,因为每次更新都需要重新构建并部署整个网站

        SSG 虽然可以很好的将页面静态资源进行提前进行构建并部署到CDN来提高用户访问效率,也很好的解决了白屏时间过长和 SEO 不友好的问题。但若要生成的页面过多,比如有十几万个,那么很难在服务端一次性生成,全量预渲染整个网站是不现实的,这时,就需要使用到ISR做增量渲染了。

从 SSG 到 ISR/DPR

ISR增量渲染

        Next.js 推出的 ISR(Incremental Static Regeneration) 方案,是基于SSG进行实现的,对比SSG只是增加了Server端的逻辑。

        允许在应用运行时再重新生成每个页面 HTML(允许网站在不需要重新构建整个站点的情况下,仅对发生变化的部分进行更新和重新生成)。这样即使有海量页面,也能使用上 SSG 的特性。一般来说,使用 ISR 需要 getStaticPathsgetStaticProps 同时配合使用。

  • 关键性的页面(如网站首页、热点数据等)预渲染为静态页面,缓存至 CDN,保证最佳的访问性能

  • 非关键性的页面(如流量很少的老旧内容)先响应 fallback 内容,然后浏览器渲染(CSR)为实际数据;同时对页面进行异步预渲染,之后缓存至 CDN,提升后续用户访问的性能

        页面的更新始终返回 CDN 的缓存数据(无论是否过期);如果数据已经过期,那么触发异步的预渲染,异步更新 CDN 的缓存。请求页面,页面数据未过期,返回预渲染页面;页面数据过期,拉取最新数据,重新预渲染。

        优点:

1、具有 SSG 的所有优点,并且它减少了应用程序的构建和部署时间,因为它避免了在构建期间预渲染所有页面

2、如果数据有任何更新,则重新生成页面,而无需重建整个应用程序

3、提高了网站的更新效率

        缺点:

1、对于没有预渲染的页面,用户首次访问将会看到一个 fallback 页面,此时服务端才开始渲染页面,直到渲染完毕。这就导致用户体验上的不一致

2、对于已经被预渲染的页面,用户直接从 CDN 加载,但这些页面可能是已经过期的,甚至过期很久的,只有在用户刷新一次,第二次访问之后,才能看到新的数据。对于电商这样的场景而言,是不可接受的(比如商品已经卖完了,但用户看到的过期数据上显示还有)

3、实现起来可能较为复杂,需要额外的配置和管理

DPR分布式持久渲染

        DPR 是一种利用分布式计算资源进行持续渲染的技术。它可能涉及在多个节点上并行处理渲染任务,以提高渲染效率和可扩展性。然而,DPR 并不是一个广泛认可或标准化的前端渲染技术术语,它可能代表了某种特定技术或方案的概念。

        DPR 本质上讲,是对 ISR 的模型做了几处改动,并且搭配上 CDN 的能力:

1、去除了 fallback 行为,而是直接用 On-demand Builder(按需构建器)来响应未经过预渲染的页面,然后将结果缓存至 CDN

2、数据页面过期时,不再响应过期的缓存页面,而是 CDN 回源到 Builder 上,渲染出最新的数据

3、每次发布新版本时,自动清除 CDN 的缓存数据

        优点:

1、提高渲染效率和可扩展性。

2、利用分布式资源优化渲染性能。

        缺点:

1、新页面访问可能会触发 On-demand Builder 同步渲染,导致当次请求响应时间比较长;

2、DoS 攻击比较难防御,因为攻击者可能会大量访问新页面,导致 Builder 被大量并行运行,这里需要平台方实现 Builder 的归一化和串行运行

混合渲染模式

        混合渲染模式(Hybrid Rendering Modes)是现代Web开发中非常流行且有效的策略,旨在结合不同渲染技术的优点以优化网站性能和用户体验。

SSR + CSR

        SSR 似乎已经解决了 CSR 带来的问题,但 CSR 也有自己的优势,比如使用 CSR 时,页面切换无需刷新,无需重新请求整个 HTML 的内容。因此,我们可以各取所长,各补其短,于是就有了 SSR + CSR 的方案:

  • 首次加载页面走 SSR:保证首屏加载速度的同时,并且满足 SEO 的诉求

  • 页面切换走 CSR:Next.js 会发起一次网络请求,执行 getServerSideProps 函数,拿到它返回的数据后,进行页面渲染

    二者的有机结合,可以大大减少后端服务器的压力和成本,还能提高页面切换的速度,进一步提升用户的体验。

        优势:

1、首屏加载速度快:通过SSR生成初始的HTML,可以确保首屏内容迅速展示给用户,这对SEO和用户体验都至关重要。

2、后续页面切换流畅:页面切换时,CSR接管页面渲染,通过JavaScript动态更新页面内容,避免了整页刷新,提升了用户体验。

3、减轻服务器压力:非首次访问的页面切换主要由客户端处理,减少了服务器的渲染负担。

        适用于需要快速首屏加载且后续页面交互频繁的Web应用,如电商平台、新闻网站等。

SSG + CSR

        SSR 需要较高的服务器运维成本。对于某些静态网站或者实时性要求较低的网站来说,是没有必要使用 SSR 的。那么如果用 SSG 代替 SSR,使用 SSG + CSR 的方案,是不是会更好:

  • 静态内容走 SSG:对于页面中较为静态的内容,比如导航栏、布局等,可以在编译构建时预先渲染静态 HTML

  • 动态内容走 CSR:一般会在 useEffect 中请求接口获取动态数据,然后进行页面重新渲染

    虽然从体验来说,动态内容需要页面重新渲染后才能出现,体验上没有 SSR 好,但是避免 SSR 带来的高额服务器成本的同时,也能保证首屏渲染时间不会太长,相比纯 CSR 来说,还是提升了用户体验。

        优势:

1、低成本高效能:SSG预先生成静态HTML,部署到CDN后,可以高效分发内容,降低了服务器成本。

2、动态内容灵活更新:CSR允许页面在客户端根据用户交互动态加载数据,保持了应用的灵活性和响应性。

3、SEO友好:由于初始页面是静态的,因此仍然对SEO友好。

        适用于内容相对静态但偶尔需要动态更新的网站,如博客、文档站点等。

SSG + SSR

        在上面介绍的 ISR 方案时提及过,ISR 的实质是 SSG + SSR:

  • 静态内容走 SSG:编译构建时把相对静态的页面预先渲染生成 HTML,浏览器请求时直接返回静态 HTML

  • 动态内容走 SSR:浏览器请求未预先渲染的页面,在运行时通过 SSR 渲染生成页面,然后返回到浏览器,并缓存静态 HTML,下次命中缓存时直接返回

    ISR 相比于 SSG + CSR 来说,动态内容可以直接直出,进一步提升了首次访问页面时的体验;相比于 SSR + CSR 来说,减少没必要的静态页面渲染,节省了一部分后端服务器成本。

        优势:

1、结合SSG和SSR的优点:静态内容通过SSG预先渲染,提高加载速度和SEO;动态内容通过SSR在请求时生成,保证内容的新鲜度。

2、智能缓存管理:ISR允许根据内容更新的频率智能地缓存和重新生成页面,减少了不必要的渲染工作。

3、成本效益:相比纯SSR,ISR减少了不必要的渲染操作,从而降低了服务器成本。

        适用于需要频繁更新部分页面内容但又希望保持高性能和SEO的网站,如社交媒体、新闻聚合网站等。

同构

        并不是所有的 WEB 应用都必须使用 SSR,需要权衡利弊,因为服务端渲染会带来以下问题:

  • 代码复杂度增加。为了实现服务端渲染,应用代码中需要兼容服务端和客户端两种运行情况,而一部分依赖的外部扩展库却只能在客户端运行,需要对其进行特殊处理,才能在服务器渲染应用程序中运行。

  • 需要更多的服务器负载均衡。由于服务器增加了渲染HTML的需求,使得原本只需要输出静态资源文件的 node 服务,新增了数据获取的 IO 和渲染 HTML 的 CPU 占用,如果流量突然暴增,有可能导致服务器down机,因此需要使用响应的缓存策略和准备相应的服务器负载。

  • 涉及构建设置和部署的更多要求。与可以部署在任何静态文件服务器上的完全静态单页面应用程序 (SPA) 不同,服务器渲染应用程序,需要处于 Node.js server 运行环境。

        假如我们需要在项目中使用服务端渲染,我们需要做什么呢?那就是同构我们的项目。

        基于 CSR 和 SSR 各自的优缺点,如果可以将它们进行结合,那么就可以实现互补,而这也就是同构渲染需要做的事,其中的同构就是指应用代码的主体可以同时运行在服务端和客户端。

同构定义

        同构(Isomorphic)或称为通用(Universal)渲染,是Web开发中一种重要的模式,特别是在使用现代JavaScript框架(如React, Vue.js等)时。它允许开发者编写一套代码,这些代码既可以在服务器上执行,用于生成初始的HTML,也可以在客户端执行,以支持后续的交互和页面更新。这种模式的实现需要解决几个关键问题,包括路由、组件、数据模型的共享和兼容性问题。

        在服务端渲染中,有两种页面渲染的方式:

  • 前端服务器通过请求后端服务器获取数据并组装HTML返回给浏览器,浏览器直接解析HTML后渲染页面

  • 浏览器在交互过程中,请求新的数据并动态更新渲染页面

        这两种渲染方式有一个不同点就是,一个是在服务端中组装html的,一个是在客户端中组装html的,运行环境是不一样的。所谓同构,就是让一份代码,既可以在服务端中执行,也可以在客户端中执行,并且执行的效果都是一样的,都是完成这个html的组装,正确的显示页面。也就是说,一份代码,既可以客户端渲染,也可以服务端渲染。

        同构渲染意味着使用 Node.js 和 JavaScript,因为它们允许重用库,并使浏览 JavaScript 代码能够在 Node.js 环境中运行,而无需进行太多修改。构建同构应用的最终目的是从一份项目源码中构建出 2 份 JavaScript 代码。一份用于在Node.js环境中快速渲染出HTML页面,提高首屏加载速度和SEO性能;另一份用于在浏览器中运行,实现页面的动态交互、数据绑定和路由跳转等功能,提供丰富的用户体验。

        优势:

1、首屏加载速度快:由于服务器已经预先渲染了HTML,用户首次访问页面时可以立即看到内容,而无需等待JavaScript执行和DOM构建。

2、SEO友好:搜索引擎爬虫可以直接解析由服务器返回的HTML,使得内容更容易被索引。

3、客户端体验流畅:一旦初始页面加载完成,客户端的JavaScript接管页面,提供快速的交互和页面更新。

同构条件

        为了实现同构,我们需要满足什么条件呢?首先,我们思考一个应用中一个页面的组成,假如我们使用的是Vue.js,当我们打开一个页面时,首先是打开这个页面的URL,这个URL,可以通过应用的路由匹配,找到具体的页面,不同的页面有不同的视图,那么,视图是什么?从应用的角度来看,视图 = 模板 + 数据,那么在 Vue.js 中, 模板可以理解成组件,数据可以理解为数据模型,即响应式数据。所以,对于同构应用来说,我们必须实现客户端与服务端的路由、模型组件、数据模型的共享。

1、路由共享:

  • 客户端和服务端需要共享路由配置,以便在请求到达时,服务端能够找到对应的组件进行渲染。

  • 通常使用框架提供的路由库(如Vue Router, React Router)配合服务端渲染中间件(如Next.js, Nuxt.js)来实现。

2、组件共享:

  • 组件需要在客户端和服务端都能正确运行。

  • 需要注意避免在组件中使用仅客户端可用的API(如window对象)。

  • 使用条件渲染或环境变量来区分服务端和客户端的特定代码。

3、数据模型共享:

  • 数据模型(状态管理)需要在客户端和服务端之间保持同步。

  • 可以通过在服务端预取数据并在客户端初始化状态树来实现。

  • 使用如Redux, Vuex等状态管理库可以更方便地在客户端和服务端之间共享状态。

4、环境兼容性:

  • 编写兼容服务端和客户端的代码,处理全局对象(如window, document)的缺失。

  • 使用Webpack或类似工具进行代码分割和打包,确保服务端仅包含必要的代码。

5、构建和部署:

  • 需要配置适当的构建工具和服务器环境,以支持服务端渲染。

  • 确保应用能够在Node.js环境中运行,并正确处理路由和数据请求。

同构流程

服务端渲染应用快照

        在服务端,Vue 组件会被渲染为静态的 HTML 字符串,然后发送给客户端浏览器,服务端生成的 HTML 内容是在当前数据状态下应用的快照:

  • 生成应用快照的同时,还会生成当前数据状态的 初始数据,用于提供给客户端做初始化处理

  • 应用快照不具备事件绑定能力,即定义好的事件不会被注册到对应的 DOM

  • 应用快照不具备数据响应式的能力,即不具备和用户进行数据交互的能力,不会执行 beforeUpdate、updated 生命周期

  • 应用快照不具备节点挂载的能力,即不需要在服务端运行时进行节点挂载操作,不会执行 beforeMount、mounted 生命周期钩子

  • 应用快照不具备组件销毁的能力,即不会执行组件的 beforeUnMount、unMount 生命周期钩子

服务端渲染时不提供上述的功能是因为在服务端渲染根本不需要关注这些,另外也是为了使服务端的渲染压力更小,关注更少的内容。

客户端激活

        同构应用运行原理的核心在于虚拟 DOM

        在浏览器端,需要渲染这段从服务端返回的 HTML 内容,即此时页面中已经存在 组件对应的 DOM 元素,除此之外该组件还会被打包到一个 JavaScript 文件中,并在客户端被 下载、解析、执行,也就是进入 客户端激活,后续页面内容的渲染都不需要服务器进行处理动态编译处理。

客户端的 JavaScript 脚本处理核心内容:

  • 将当前页面已渲染的 DOM 元素与 Vue.js 所渲染的虚拟 DOM 之间建立联系

    • 由于 真实 DOM虚拟 DOM 对象都是树形结构,并且节点间存在相互对应关系,激活 就可以通过递归地在 真实 DOM虚拟 DOM 之间建立联系,即 vnode.el = el,并保证是从容器元素的第一个子节点开始,即 el.firstChild

  • 为页面中的 DOM 元素添加事件绑定,使得页面本身支持事件交互

  • Vue.jsHTML 页面中提取由服务端序列化后发送过来的数据,用于初始化整个 Vue.js 的应用程序

如何实现同构渲染

1、使用Vue、React等框架的官方解决方案。优点是有助于理解原理,缺点是需要搭建环境,比较麻烦

服务端 要渲染 Vue 组件 意味着需要处理 *.vue*.css*.ts 等依赖模块,而这些是 node 本身就不能处理的内容,也不是 renderToString 能够处理的,因此需要借助 打包构建工具(如 webpack) 进行处理。

客户端 实际也需要一个独立的客户端构建版本,虽然最新版本的 Node.js 完全支持 ES2015 特性,但对于旧的浏览器仍然需要对代码进行转译、兼容处理。

③ 基本思路,使用 webpack 同时打包客户端和服务端应用,其中服务端的包会被引入到服务端用来渲染 HTML,同时客户端的包会被送到浏览器用于 激活静态标记

④ 与之对应的两个入口文件就是:entry-client.jsentry-server.js(更多具体的配置可参见 官方文档)

2、使用第三方解决方案,比如:React生态的Next.js和Vue生态的Nuxt.js

参考资料:

【万字长文警告】从头到尾彻底理解服务端渲染SSR原理 - 掘金 (juejin.cn)

新一代Web技术栈的演进:SSR/SSG/ISR/DPR都在做什么? (qq.com)

Vuejs设计与实现 —— 同构渲染 - 掘金 (juejin.cn)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/385155.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RedHat9 | Ansible 角色

环境版本说明 RedHat9 [Red Hat Enterprise Linux release 9.0]Ansible [core 2.13.3]Python [3.9.10]jinja [3.1.2] 描述角色结构 Playbook可能比较冗长且负载,也可能存在大量的重复代码。而角色(roles)可以用于层次性结构化的组织playbo…

55. 跳跃游戏【 力扣(LeetCode) 】

一、题目描述 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。 二、测试用…

在vue中优雅地异步引入(懒加载)腾讯地图API

背景 接到一个需求需要在网站首页显示使用腾讯地图展示公司所在地。一开始我直接全局引入了腾讯地图js,结果发现在用户打开登陆页面的时候首页比较缓慢,为了提高用户登陆的加载效率,需要优化为异步引入。 思路 根据官网的示例,…

SQL 注入漏洞详解 - Union 注入

1)漏洞简介 SQL 注入简介 SQL 注入 即是指 Web 应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在 Web 应用程序中事先定义好的查询语句的结尾上添加额外的 SQL 语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,…

【前端 02】新浪新闻项目-初步使用CSS来排版

在今天的博文中,我们将围绕“新浪新闻”项目,深入探讨HTML和CSS在网页制作中的基础应用。通过具体实例,我们将学习如何设置图片、标题、超链接以及文本排版,同时了解CSS的引入方式和选择器优先级,以及视频和音频标签的…

分布式光伏并网AM5SE-IS防孤岛保护装置介绍——安科瑞 叶西平

产品简介 功能: AM5SE-IS防孤岛保护装置主要适用于35kV、10kV及低压380V光伏发电、燃气发电等新能源并网供电系统。当发生孤岛现象时,可以快速切除并网点,使本站与电网侧快速脱离,保证整个电站和相关维护人员的生命安全。 应用…

Hello 算法:动画图解、一键运行的数据结构与算法教程

Hello 算法 《Hello 算法》是一份开源、免费的数据结构与算法入门教程,特别适合新手。全书采用动画图解,内容清晰易懂,学习曲线平滑,引导初学者探索数据结构与算法的知识地图。源代码可以一键运行,帮助读者通过练习提…

WEB攻防-通用漏洞-SQL 读写注入-MYSQLMSSQLPostgreSQL

什么是高权限注入 高权限注入指的是攻击者通过SQL注入漏洞,利用具有高级权限的数据库账户(如MYSQL的root用户、MSSQL的sa用户、PostgreSQL的dba用户)执行恶意SQL语句。这些高级权限账户能够访问和修改数据库中的所有数据,甚至执行…

springboot中使用knife4j访问接口文档的一系列问题

springboot中使用knife4j访问接口文档的一系列问题 1.个人介绍 🎉🎉🎉欢迎来到我的博客,我是一名自学了2年半前端的大一学生,熟悉的技术是JavaScript与Vue.目前正在往全栈方向前进, 如果我的博客给您带来了帮助欢迎您关注我,我将会持续不断的…

用Java手写jvm之实现查找class

写在前面 完成类加载器加载class的三阶段,加载,解析,初始化中的加载😀😀😀 源码 。 jvm想要运行class,是根据类全限定名称来从特定的位置基于类加载器来查找的,分别如下:…

解决R语言找不到系统库导致的报错

1、基本需知 1.1、系统库 系统库(System library)是一组预先编写和编译好的软件模块集合,用于支持操作系统的基本功能和提供一些常见的服务。这些库通常由操作系统或第三方开发者提供,并且在系统安装过程中被预装或者用户可以额…

崖山异构数据库迁移利器YMP初体验-Oracle迁移YashanDB

前言 首届YashanDB「迁移体验官」开放后,陆续收到「体验官」们的投稿,小崖在此把优秀的投稿文章分享给大家~今天分享的用户文章是《崖山异构数据库迁移利器YMP初体验-Oracle迁移YashanDB》(作者:小草),满满…

【vue前端项目实战案例】之Vue仿饿了么App

本文将介绍一款仿“饿了么”商家页面的App。该案例是基于 Vue2.0 Vue Router webpack ES6 等技术栈实现的一款外卖类App,适合初学者进行学习。 项目源码下载链接在文章末尾 1 项目概述 该项目是一款仿“饿了么”商家页面的外卖类App,主要有以下功能…

51单片机嵌入式开发:17、STC89C52的嵌入式 遥控器 控制步进电机 转速 和 转向 操作并 printf打印信息

51单片机嵌入式开发 STC89C52的嵌入式 遥控器 控制步进电机 转速 和 转向 操作并 printf打印信息 51单片机嵌入式开发STC89C52的嵌入式 遥控器 控制步进电机 转速 和 转向 操作并 printf打印信息1 概述2 硬件电路2.1 遥控器2.2 红外接收器电路2.3 STC89C52单片机电路2.4 数码管…

SpringBoot集成Sharding-JDBC实现分库分表

本文已收录于专栏 《中间件合集》 目录 版本介绍背景介绍拆分方式集成并测试1.引入依赖2.创建库和表3.pom文件配置4.编写测试类Entity层Mapper接口MapperXML文件测试类 5.运行结果 自定义分片规则定义分片类编写pom文件 总结提升 版本介绍 SpringBoot的版本是: 2.3.…

IDEA Maven使用HTTP代理,解决Could not transfer artifact org.xxx问题

文章目录 一、前言二、遇到问题三、分析问题四、HTTP代理五、重新编译验证 一、前言 遇到这个问题,有两种解决办法 IDEA Maven使用HTTP代理,解决Could not transfer artifact org.xxx问题IDEA Maven使用国内镜像,解决Could not transfer arti…

C语言分支语句之if的一些用法

目录 引言C语言结构 1. if 语句1.1 if1.2 else 2. 分支中包含多条语句3. 多重选择 else if4. 嵌套if5. 悬空else / else与if配对问题 引言 C语言作为一种非常常用的编程语言,具有灵活强大的循环和分支结构。循环结构允许我们重复执行一段代码,而分支结构…

【网络爬虫技术】(1·绪论)

🌈 个人主页:十二月的猫-CSDN博客 🔥 系列专栏: 🏀网络爬虫开发技术入门_十二月的猫的博客-CSDN博客 💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 目录 …

本地部署Graphhopper路径规划服务(graphhopper.sh启动版)

文章目录 文章参考源码获取一、配置Java环境变量二、配置Maven环境变量三、构建graphhopper步骤1. 下载数据2. 配置graphhopper配置文件config-example.yml3. 在项目中启动命令行执行./graphhopper.sh build3.1|、遇到的问题3.1.1、pom.xml中front-maven-plugin-无法下载npm6.1…

跨境电商独立站:Shopify/Wordpress/店匠选哪个?

在面对不断增加的平台运营压力时,不少跨境电商的商家逐渐将注意力转向建立自己的独立站。据《中国跨境出口电商发展报告(2022)》所示,中国拥有的独立站数量在2022年已接近20万个,这表明独立站已成为卖家拓展海外市场的…