这个来自之前的培训,删掉了一些业务相关的,参考了很多资料(参考列表),谢谢前辈,what's事情?随着互联网架构的不断演进,前端技术框架发生了翻天覆地的变化,从后台输出页面到后台MVC,再到前端MVC、MVP、MVVM,再到VirtualDOM和MNV*。从整体上看,前端也在朝着模块化、组件化、高性能Web开发建模的方向快速发展。除了传统的桌面浏览器端Web应用,前端技术栈在服务端或移动端的尝试和发展从未停止,并形成了一系列成熟的解决方案。前端技术栈能解决的不仅仅是页面上的问题,前端工程师的追求也不仅仅是页面上的技术。跨后端技术全栈工程师已经成为近几年非常热门的关键词。从最早的MEAN技术栈到后端直出,到现在前后端同构,前端越来越多的通过结合Node.js的开发模式进行开发。越被开发者认可,并在越来越多的项目中实践。前端开发者热衷于在Node上开发,原因如下:Node是一个事件驱动、非阻塞的服务器,非常适合处理并发请求,因此构建在Node上的应用服务比其他技术具有更好的服务性能。要乖。Node端运行JavaScript,对于前端开发者来说学习成本相对较低,需要关注的问题也相对于前端更加纯粹。作为前端工程师,确实需要掌握一门后端语言来辅助自己的技术学习。Node处理数据渲染的方式可以解决前端无法解决的问题,这种优势体现在大型Web应用场景中。重要原因。Node后端开发Node.js是一个基于ChromeV8引擎的JavaScript运行时。有一个叫RyanDahl的歪果仁,他的工作是用C/C++编写高性能的Web服务。高性能,异步IO和事件驱动是基本原则,但是用C/C写太痛苦了。于是这个人开始设想用高级语言开发Web服务。他评估了很多高级语言,发现虽然很多语言同时提供了同步IO和异步IO,但是开发者一旦使用了同步IO,就再也懒得写异步IO了,所以,最终,Ryan瞄准了JavaScript.2009年,Ryan正式推出基于JavaScript语言和V8引擎的开源Web服务器项目,命名为Node.js。Node第一次将JavaScript引入到后端服务器开发中,全世界已经有无数的JavaScript开发者,Node一下子火了起来。Node最大的优势在于借助JavaScript天生的事件驱动机制和V8高性能引擎,可以轻松编写出高性能的Web服务。阻塞和非阻塞阻塞是指Node.js中的其他JavaScript命令必须等待非JavaScript操作完成才能执行。这是因为发生阻塞时,事件机制无法继续运行JavaScript。在Node.js中,由于CPU密集型操作,JavaScript表现不佳。而不是等待非JavaScript操作(例如I/O)。这称为阻塞。阻塞方法是同步执行的,非阻塞方法是异步执行的。要使用文件系统模块读取文件,sync方法如下所示:constfs=require('fs');constdata=fs.readFileSync('/file.md');//此处将阻止等效的异步版本:constfs=require('fs');fs.readFile('/file.md',(err,data)=>{if(err)throwerr;});在第二个示例中,fs.readFile()是非阻塞的,因此JavaScript将继续执行而不会阻塞,这是高效吞吐量的绝佳设计。Node.js中的JavaScript执行是单线程的,因此并行性与事件循环能力有关(即在其他任务完成后处理JavaScript回调函数的能力)。任何试图并行运行的代码都必须让事件循环器在非JavaScript操作上运行,比如I/O操作。例如,每个对服务器的请求需要50毫秒才能完成,其中45毫秒是数据库操作,可以通过异步操作完成。选择非阻塞操作可以释放这45毫秒来处理其他请求的操作。这是选择阻塞和非阻塞方法的最大区别。Node.js中的事件轮询机制不同于其他语言。其他语言一般需要创建线程来处理并行任务。MEANNode早期并没有现在这么复杂,相关的技术和语言标准也不成熟。Node开发最常用的解决方案是使用Express作为小型网站建设的Web框架,结合M(Mysql)、E(Express)、A(Angular)、N(Node)是最典型的主流技术是MEAN,直到今天MEAN技术组合仍在沿用。前端一般使用Angular来管理和实现页面应用,服务端的web框架主要是Express,同时使用免费开源的MongoDB数据库,可以快速搭建一个web应用。今天可能没有必要选择使用它,因为已经有很多成熟的解决方案可以替代。可以使用其他各种前后端框架灵活组合,作为MEAN的备选方案。比如Vue和React可以代替Angular,Koa可以代替Express,还有很多数据库选择。Node后端数据渲染对于前端开发者来说,在开发大型Web应用时,往往不需要对整个应用后台的架构进行彻底的重新设计。更多的情况下,需要结合Node的能力来帮助我们解决前后端开发分离的问题。模式无法解决的问题。我们先来看看通常的前后端分离开发模式存在的问题,以及使用Node端服务如何帮助我们解决这些问题:SPA场景下的SEO问题一般而言,SPA应用或开发模式前-端后端分离接下来页面加载的基本流程是:浏览器首先加载一个空页面和JavaScript脚本。然后异步请求接口获取数据。渲染后将页面数据内容展示给用户。那么问题来了,当搜索引擎抓取页面,解析页面HTML中的关键字、描述或者其他内容时,JavaScript还没有被调用执行,搜索引擎抓取到的只是一个空页面,所以无法获取页面上
的具体内容,影响搜索引擎收录页面的内容排名。虽然我们会在空页面的中添加关键字和描述内容,但这肯定是不够的,因为页面的关键文本内容描述还没有被搜索引擎获取到。如果使用Node后端数据渲染(有人称之为直出或者服务端渲染SSR),在页面被请求时将内容渲染到页面输出,那么搜索引擎获取到的HTML中已经包含页面内容完整,页面也更容易找到。前端页面渲染显示慢的问题除了SEO问题外,在前后端分离的开发模式下,在JavaScript执行渲染(或提示用户加载)之前页面是一片空白。用户查看数据时已经花费的网络等待时间包括:DOM下载时间+DOM解析时间+JavaScript文件请求时间+JavaScript部分执行时间+接口请求时间+DOM渲染时间。这个时候,当用户看到页面数据的时候,已经是经过了三个串行的网络资源请求。如果直接使用后端渲染数据,首先SEO问题就不存在了。用户浏览器加载并解析DOM内容后,可以立即显示出来,网络加载的问题也解决了。其他逻辑操作(如事件绑定、滚动加载内容)可以按需异步加载,从而大大减少页面内容显示的时间。一般后台页面数据直接输出的一般架构设计如下:直接输出层接受前端的路由请求,在Node端的Controller层异步请求服务访问层接口,获取Model数据并进行组装,然后提取出对应的Node端View模板,将HTML输出渲染到用户浏览器,而不是通过前端JavaScript请求动态数据再渲染。不仅如此,直出层还可以根据不同的浏览器userAgent提取不同的模板渲染页面返回给不同的用户浏览器,所以这种实现方式不仅非常适合大型应用服务的实现场景,而且也可以很方便的实现。直接响应内容。前后端同构在前后端分离的开发模式上增加了一个直出层,解决了SEO和数据加载显示慢的问题。但是有两个新的问题:前端开发实现转移到直出层,需要修改原有的开发模式以适应直出层内容的开发,比如修改后台-端模板适应现有的开发模式,因此我们不得不维护两套不同的前后端模板或技术实现——前端渲染实现逻辑和后端直出实现逻辑,尽管它们可能都是用JavaScript编写的。如果是在移动混合应用上,离线包机制的实现可能会出现问题。因为HTML结构每次都是直接从后端发送给前端,所以离线缓存HTML文件比较困难,只能缓存其他静态文件。在HybridApp的应用场景中,我们其实希望实现的是在移动端第一次打开页面时使用后端直接输出内容解决加载慢和SEO问题,同时利用客户端本地缓存当有离线缓存的时候可以通过从静态文件中拉取数据返回渲染来实现,或者以后高端浏览器支持HTTP2时使用前端渲染,低端浏览器不支持时直接输出支持HTTP2。因此,需要一个完整的开发方法,与原有的开发方法一致,同时适用于前后端分离的开发模式和后端数据渲染模板开发方法。这种开发模式就是我们所说的前后端同构。IsomorphicCore同构的目的是只开发一套项目代码,不仅可以用于前端JavaScript加载渲染,还可以用于后端直出渲染。为什么可以这样做?和前端渲染数据内容一样,页面直接输出层的内容也是由数据加模板编译生成的。前端渲染和后台直接输出方式生成DOM结构的区别仅在于数据和模板的渲染发生时。如果使用前后端都可以编译数据的模板系统,就可以使用同一套开发代码分别在前后端进行数据渲染和分析。因此,前后端同构的核心问题是实现前后端数据渲染的统一。同构的优势除了解决前后端开发方式的问题,前后端同构网站还有一些明显的优势:可以方便地选择使用前端渲染数据还是直接使用后台页面数据根据用户需要;开发者只需要维护一套前端代码,就可以使用原有的前端项目组件管理、打包和构建方式,根据不同的构建指令生成相似的前后端数据模板或组件来执行前后端分析,所以这个很重要,DOM结构层的开发方法要保持一致。前后端同构的实现原理基于数据模板的前后端同构方案早在前端MVC开发时代,前端模板就被广泛使用,比如Mustache,Handlebar等基本原理是将模板描述语法和数据拼接生成HTML代码字符串插入到页面特定元素中渲染数据。同样,后端直出层也可以使用该方法渲染数据,生成HTML字符串输出到页面。如果前后端使用相同的模板解析引擎,那么我们只需要编写相同的模板描述语法结构就可以分别渲染前后端。比如同一个模板: