Fresh大火!下一代Web全栈框架!
大家好,很高兴又见面了,我是高级前端进阶,由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!
高级前端进阶前言
Fresh是面向JavaScript和TypeScript开发人员的全栈现代Web框架,旨在提供创建高质量、高性能、个性化Web应用程序的新方式。开发者可以使用Fresh来创建主页、博客、大型Web应用程序(如GitHub或Twitter)等等。
Fresh的核心是路由框架和模板引擎的组合,可在服务器上按需渲染页面。除了服务器上的即时(JIT)渲染之外,Fresh还提供了一个接口,用于在客户端无缝渲染某些组件,以实现最大程度的可交互性。Fresh框架使用Preact和JSX在服务器和客户端上进行渲染和模板化。Fresh底层基于Preact、并使用基于孤岛架构的客户端水合作用。
同时,Fresh没有任何构建步骤,开发者的代码可直接在服务端、客户端运行。TypeScript或JSX到纯JavaScript的任何必要转换都是在需要时即时完成的。从而极大的加快迭代、部署效率。开发者可以借助于deno手动将新项目部署到任何平台,但是为了最佳体验建议部署在类似DenoDeploy等边缘运行时。
目前Fresh在Github上有10。2k的star,400的fork、超过120的开发者贡献代码。因此,这篇文章将详细介绍Fresh提供的功能。1。什么是Deno
Deno(dino,发音为deeno)是一个安全的JavaScript、TypeScript和WebAssembly运行时,同时具有出色的开发人员体验。它建立在V8(谷歌的JavaScript运行时引擎)、Rust和Tokio之上。Deno构建于以下几个核心能力:Rust(Deno的核心是用Rust编写的,Node的核心是用C编写的)Tokio(用Rust编写的事件循环)TypeScript(Deno开箱即用地支持JavaScript和TypeScript)V8(Google的JavaScript运行时用于Chrome和Node等)
下表从语言支持、包管理、安全权限、代码集成、机器执行等诸多维度展示了Node。js和Deno的主要区别:
Deno提供了以下核心特性:提供网络平台功能,采用网络平台标准。如使用ES模块、webworker、支持fetch默认安全。除非明确启用,否则不得访问文件、网络或环境。开箱即用地支持TypeScript发布单个可执行文件(deno)提供内置开发工具,如代码格式化程序(denofmt)、linter(denolint)、测试运行器(denotest)和用于编辑器的语言服务器有一组经过审查(审核)的标准模块,可以与Deno一起使用可以将脚本打包到单个JavaScript文件或可执行文件中。支持使用现有的npm模块2。什么是Fresh?
Fresh建立在Deno之上,开发者使用TypeScript编写应用程序。Fresh自称是用于服务器端渲染的下一代全栈Web框架,它类似于其他全栈Web框架,如:Django、RubyonRails、Symfony或Larvel等等。
从本质上讲,Fresh是一个路由框架,它使用Preact(一种轻量级的React替代方案)作为模板引擎。模板引擎使开发者能够在应用程序中使用静态模板文件。Fresh负责将模板中的变量替换为实际值,并将模板转换为发送给客户端的HTML文件。
深入了解Fresh旨在解决的问题之前,大家一起先看看Deno博客中的几段话:1。客户端渲染很昂贵,React等框架通常会在每次请求时向用户发送数百KB的客户端JavaScript。这些JS包通常只是渲染静态内容,但这些静态内容也可以作为纯HTML提供。
2。一些框架也支持服务器端渲染,这有助于通过在服务器上预渲染来减少页面加载时间。但是大多数当前实现仍然将完整的应用程序渲染结构发送给客户端,以便页面可以在客户端上完全重新渲染。
3。这是一个糟糕的体验,客户端JavaScript非常昂贵,它会显著降低用户体验,大大增加移动设备的功耗,而且通常不是很健壮。
那么Fresh与Next。js或Remix等其他JavaScript框架的工作方式究竟有何不同?以Next。js为例,它预渲染每个页面,本质上意味着它提前为页面生成HTML,而不是让客户端去做。这会带来更好的性能和SEO,因为机器人能够更有效地抓取站点内容。当一个页面被浏览器加载时,JavaScript代码就会运行,并通过一个称为补水(Hydration)的过程使页面完全交互。
Fresh与Next。js类似,无需将JavaScript代码发送到浏览器,而是在服务器上将所有内容渲染为静态HTML。但是,网站需要交互性,而仅静态HTML并不能解决交互问题,这就是孤岛架构的用武之地。
Fresh有一个islands目录,其中包含所有交互式组件,这些组件需要将JavaScript发送到浏览器,而非islands目录的所有其他组件将渲染为静态HTML。这就是Fresh采用的部分水化(PartialHydration)机制。3。Fresh特点
与所有其他JavaScript框架一样,Fresh为开发者提供了很多优秀的功能。接下来一起看看这些功能是什么,以及它们的作用。
3。1边缘即时渲染
Fresh在服务器上将所有内容渲染为静态HTML。最重要的是,当开发者在Fresh中创建API路由时,它基于FetchAPI接口,允许将其部署到无服务器边缘函数(ServerlessEdgeFunctions),例如DenoDeploy。3。2基于孤岛架构的客户水合
本质上,基于孤岛架构的客户端水合适用于应用程序的一小部分内容,该部分需要JavaScript才能进行交互。例如,在Fresh主页底部有一个计数器,它可以被水合以提供更好的交互性。
下图比较了孤岛架构、SSR、渐进式水合的不同。其中Marko、Astro、Qwik、Fresh等框架都是采用这种孤岛架构进行服务器端渲染。
SSR:一次性渲染所有组件,然后客户端水合渐进式水合:一次性渲染所有组件,只对关键组件水合、然后渐进式水合其他组件s孤岛架构:静态组件由服务端渲染为静态HTML,交互式组件动态加载JavaScript脚本3。3零运行时开销
这个功能源自之前谈到的基于岛屿的客户端水合作用。默认情况下,在应用程序中,Fresh不会向浏览器发送JavaScript,只是发送一个静态的HTML文件。3。4零构建
虽然Fresh旨在部署到DenoDeploy,但实际上它可以部署到任何运行基于Deno的Web服务器的系统或平台。下面示例表示将Fresh部署到运行Docker容器的平台。
为Docker打包Fresh应用程序时,务必在容器中设置DENODEPLOYMENTID环境变量。此变量需要设置为一个不透明的字符串ID,代表当前正在运行的应用程序的版本。版本可以是Git提交的哈希,或项目中所有文件的哈希。比如下面的Dockerfile文件内容:
在Git存储库中构建Docker映像:dockerbuildbuildargGITREVISION(gitrevparseHEAD)tmyfreshapp。
然后运行Docker容器:dockerruntip80:8000myfreshapp3。5无需配置
开发者无需真正配置任何内容即可开始使用Fresh开发应用程序,只需使用CLI即可立即开始!3。6开箱即用的TypeScript支持
开发者不需要像在Node。js中那样在Fresh中单独配置TypeScript,这与Deno本身开箱即用的支持TypeScript类似。4。Fresh示例4。1实例化项目
Fresh需要DenoCLI1。25。0或更高版本,可以通过下面命令安装或更新。denorunArhttps:fresh。deno。devmyproject
进入新建的项目目录,运行如下命令启动开发服务器:denotaskstart
现在可以在浏览器中打开http:localhost:8000来查看该页面。4。2Fresh组件拆分
Fresh框架将构成页面的各种组件,分为route和island两类,约定存放在routes和islands两个目录,Fresh处理这两类组件的方式完全不同:RouteComponent:仅在服务端执行,直接响应SSR渲染出的HTML给客户端,在客户端不会加载和执行任何JS代码,无需hydrate。IslandComponent:不仅在服务端执行,JS也会在客户端加载,同时需要hydrate,所以Island可以响应用户的交互。
这两类组件便是Fresh框架对孤岛架构(IslandsArchitecture)的实现。在这个架构中,Routes负责静态内容,无需交互,而Islands通过JS来提升页面交互性。Islands之间相互独立,一个崩溃不会影响另一个,同时hydrate也保存独立,hydrate完成后即可立即响应用户的交互(无任务阻塞情况下)。
Route和Island这两种组件本质上都是Preact组件。Island比Route更正常一些,和常规的参与SSR的组件没太大区别,任何需要在客户端执行JS的区块,都必须抽成一个IslandComponent独立出去。而Route更像是被Fresh当做模板引擎使用使用。
下面是官方Fresh的一个简单示例:routesindex。tsxRoute组件importCounterfrom。。islandsCounter。tsx;exportdefaultfunctionHome(){return(pWelcometoFresh。Trytoupdatethismessageinthe。routesindex。tsxfile,andrefresh。Counterstart{3});}islandsCounter。tsxislands组件import{useState}frompreacthooks;import{ISBROWSER}fromfreshruntime。ts;interfaceCounterProps{start:number;}exportdefaultfunctionCounter(props:CounterProps){const〔count,setCount〕useState(props。start);return(p{count}{disabled具有交互性}buttononClick{()setCount(count1)}disabled{!ISBROWSER}1buttonbuttononClick{()setCount(count1)}disabled{!ISBROWSER}1button);}大家好,很高兴又见面了,我是高级前端进阶,由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!
运行效果如下:
可以看到,客户端加载的JS代码很少:main。js和chunkTDJO6WAF。js主要是Fresh的runtime代码和preactislandcounter。js就是的Island组件
如果开发者希望添加更多的可交互组件,与islandcounter。js一样,需要独立为一个个互不影响的island组件。
需要注意的是:Fresh内部强依赖Preact,通过Preact将所有组件渲染为HTML,给Islands打好标记。同时JS的依赖收集根据约定的目录控制好范围。在客户端,使用少量运行时和Preact,完成hydrate。5。本文总结
除了官方宣传的几个特点之外,Fresh框架还有几个特点值得关注:孤岛架构:它占了几乎全部的优点,客户端只需加载少量的JS代码、纯静态组件(页面)无需hydrate、良好的性能、支持SEO、基于组件的现代化开发模式等等。Fresh深度集成Preact:Fresh无需构建流程,可以直接在服务端渲染Preact组件。相比React,Preact在大多数情况下确实好用也够用。不像传统ReactSSR要构建两份代码分别用于server和client,Fresh拥有框架级的支持,虽然没有在生产环境大规模验证过,但这个思路确实优秀。handlerroute和componentroute:非常像是把koa、express简化处理,同时用JSX替换了传统的模板引擎,让开发者可以像写前端代码一样写后端deno应用。
当然了,Fresh目前还不是很成熟,如静态文件处理、Debug、HotReload、第三方生态等方面都还很单薄,但这并不影响学习了解它的设计思路和架构。
因为篇幅有限,文章并没有过多展开,如果有兴趣,可以在我的主页继续阅读,同时文末的参考资料提供了大量优秀文档以供学习。最后,欢迎大家点赞、评论、转发、收藏!
参考资料
https:dev。toharshhhdevfreshthenextgenjavascriptwebframeworkb39
https:keenwon。comfreshintroduction
https:keenwon。combetterreactssr
https:morioh。compa1eebaad1760
https:fresh。deno。dev
https:fresh。deno。devdocsconceptsdeployment
https:blog。openreplay。comanintroductiontofresh
https:morioh。compa1eebaad1760