原副标题:React 重蹈覆辙 Angular.js 狂蛛属?
【萨德基】开放源码架构 react-admin 和 GreenFrame 创办人,Marmelab CEO François Zaninotto 特别针对 React 引入的伺服器模块的新方式正式发布了他们的看法,虽然这是构筑 Web 应用领域开发人员的新方式,但并不适宜原有绝大多数 React ,意味著原有应用领域导入该方式就得对应用领域进行改写,因此他期望React 项目组认识到白眉林应用领域构架是两个恰当的优先选择,因此在短期内不能消亡。期望项目组能想两个更为折衷的方式。
镜像:https://marmelab.com/blog/2023/06/05/react-angularjs-moment.html
译者 | François Zaninotto翻译者 | 弯月
公司出品 | CSDN(ID:CSDNnews)
2012年,Angular.js 由此面世便发生改变了后端开发的新格局,快速取得成功。仅在一年之后,Angular 项目组面世了 Angular 2,不过他们依照几组不同的实例改写了整座原初库。很多开发者,包括我他们,都不该改写原有的应用领域程序来适应环境这些新设想。对新项目而言,Angular.js 无须是必选,因为其他架构也反之亦然出众。
2015 年,我们开始采用 React 来构筑后端。React 不但保有单纯的构架,所以还著重模块,再加之平衡的劳动生产率,不论标识符库大小不一怎样都是两个较好的优先选择。React 一炮而红,街道社区发展快速。前段时间,React 和 Next.js 项目组始终在推展伺服器模块,这是一种构筑 Web 应用领域程序的新方式,但不适宜绝大多数原有的 React 应用领域。
这种变动与否堪称从 Angular.js 到 Angular 2 的变革?React 与否已经开始重蹈覆辙 Angular.js 的狂蛛属?
注意:在本文中,我将讨论 React 和 Next.js 项目组导入的新功能。由于这两个项目组密切合作,因此很难说哪个项目组负责哪个功能。因此,我将采用“React”来指代这两个项目组。
重新学习一切
React 的核心是两个视图库。这一点没有变动,对 React 伺服器模块,你仍然可以采用 JSX 构筑模块,并渲染 props 传递进来的动态内容:
functionPlaylist( { name, tracks }) { return( < div> < h1> {name} </ h1> < table> < thead> < tr> < th> Title </ th> < th> Artist </ th> < th> Album </ th> < th> Duration </ th> </ tr> </ thead> < tbody> {tracks.map((track, index) => ( < trkey= {index}> < td> {track.title} </ td> < td> {track.artist} </ td> < td> {track.album}</ td> < td> {track.duration} </ td> </ tr> ))} </ tbody> </ table> </ div> ); }ect 或 react-query;相反,你应该在异步模块中采用 fetch:
asyncfunctionPlaylistFromId( { id }) { constresponse = awaitfetch(`/api/playlists/ ${id}` ); if(!response.ok) { // This will activate the closest `error.js` Error Boundary thrownewError( Failed to fetch data); } const{ name, tracks } = response.json; return< Playlistname= {name}tracks= {tracks}/> ; }求。
如果你想通过两个按钮来启动两个POST 动作,就必须在表单中添加fetch 函数,并采用伺服器动作,这意味著采用两个带有use server 的函数:
exportfunctionAddToFavoritesButton( { id }) { asyncfunctionaddToFavorites( data){ use server; awaitfetch( `/api/tracks/ ${id}/favorites` , { method: POST}); } return( < formaction= {addToFavorites}> < buttontype= “submit”> Add to Favorites </ button> </ form> ); }常见的 React 钩子:useState、useContext、useEffect 将导致伺服器模块出错。如果你需要这些钩子,就必须采用 use client,强制 React 在客户端渲染模块。注意,现在这个功能是默认启用的,而在Next.js中,甚至在伺服器组件出现之前,它就是默认行为了。
CSS-in-JS与伺服器模块不兼容。如果你习惯了采用 sx 或 css 属性直接设置模块样式,则必须学习 CSS Modules、Tailwind 或 Sass。在我看来,这种变化感觉像是倒退了一步:
// in app/dashboard/layout.tsx importstyles from./styles.module.css;exportdefaultfunctionDashboardLayout( {children,}: {children: React.ReactNode,}) { return< sectionclassName= {styles.dashboard}> {children} </ section> ; }/* in app/dashboard/styles.module.css */.dashboard {padding: 24px; }
那么,调试呢?我只能祝你好运。React DevTools 不显示 React 伺服器模块的详细信息。你无法在浏览器中检查模块,查看它采用的 props 或其子模块。目前,调试 React 伺服器模块只能求助于 console.log。
虽然基础的 JSX 保持不变,但伺服器模块的基本思想与客户端 JS 完全不同。即便你是一名精通 React 的开发者,也不一定对掌握伺服器模块有很大帮助。基本上,你必须重新学习所有内容,除非你熟悉 PHP。
注意:公平地说,我提出的绝大多数问题都涉及到带有“alpha”标签的功能。这些问题可能会在平衡版本正式发布之前得到解决。
生态系统为零
。事实证明,这不是唯一无法结合 React 伺服器模块一起采用的库。如果你依赖下面的工具,那么就要开始寻找替代品了:
material-ui chakra-ui Emotion styled-components React-query swr react-hook-form, 适用于大多数SaaS 提供商的 SDK 以及其他等等。这些库都采用了标准的 React 钩子,从伺服器模块调用时会失败。
如果你需要这些库,则必须采用 use client 指令将它们封装在模块中,强制客户端渲染。
强调一下:React 伺服器模块破坏了几乎所有原有的 React 第三方库,这些库的译者必须修改标识符才能兼容。也许有些译者会修改标识符,但有些不能。即使他们愿意修改,也需要一定的时间。
因此,如果你采用 React 伺服器模块启动应用领域,则不能依赖原有的 React 生态系统。
更糟糕的是:客户端 React 提供了很多日常工作需要的工具,但伺服器模块中并没有提供。例如,React Context 是管理依赖注入的绝佳解决方案。如果没有 React Context,伺服器模块就需要两个依赖注入容器,类似于Angular 的方式。如果核心项目组不提供,则不得不依靠街道社区。
与此同时,你必须手动编写很多标识符。在没有 UI Kit、表单架构、智能 API 客户端以及你喜欢的 SaaS 的 React 集成的情况下构筑 React 应用领域会变得非常具有挑战性。
当前的 React 生态系统是其最大的优势。这也是 React 如此广泛采用的原因。而 React 伺服器模块打破了这一优势。
黑魔法太多了
。浏览器检索数据,客户端脚本更新 DOM。
React建议混合伺服器端和客户端渲染,感觉就像是在采用黑魔法。你可以在伺服器模块中采用客户端模块,反之亦然。
当客户端模块渲染伺服器模块时,React 伺服器不能发送 HTML,而是发送模块树的文本表示。然后由客户端脚本在客户端渲染模块树。
如果你习惯采用HTML 或JSON 调试AJAX请求,就会大吃一惊。这里由两个RSC Wire 格式的例子(https://www.plasmic.app/blog/how-react-server-components-work#the-rsc-wire-format),React 采用这种格式将更新从伺服器模块流式传输到客户端:
M1:{ “id”: “./src/ClientComponent.client.js”, “chunks”:[ “client1”], “name”: “”} S2: “react.suspense”J0:[“$”, “@1”, null,{ “children”:[[ “$”, “span”, null,{ “children”: “Hello from server land”}],[ “$”, “$2”, null,{“fallback”: “Loading tweets…”, “children”: “@3”}]]}] M4:{ “id”: “./src/Tweet.client.js”, “chunks”:[ “client8”], “name”: “”} J3:[ “$”, “ul”, null,{ “children”:[[ “$”, “li”, null,{ “children”:[ “$”, “@4”, null,{ “tweet”:{…}}}]}],[“$”, “li”, null,{ “children”:[ “$”, “@4”, null,{ “tweet”:{…}}}]}]]}]这种格式没有文档,因为它是两个实现细节。
HTTP、JSON 和 JSX 如此流行,可读性功不可没。不过,React 伺服器模块破坏了这种模式。
React伺服器模块看似非常神秘,对绝大多数开发者而言都很难理解或调试。不确定这种变动究竟是会提高劳动生产率,还是会阻碍劳动生产率。
我们真的需要这个模块吗?
从第一原则触发考虑 Web 开发,可以合理地得出这样的结论:采用少量 AJAX 的伺服器端渲染是构筑 Web 应用领域程序的有效方式。Dan Abramov 在 2023年 Remix 大会的演讲中对React 伺服器模块背后的动机做出了解释(https://www.youtube.com/watch?v=zMf_xeGPn6s&ab_channel=Remix):
这种构架非常适宜电子商务网站、博客以及其他对 SEO有强烈要求的、以内容为中心的网站。
不过,这并不是两个新概念。多年来, 这种构架始终用于 Rails 中的 Hotwire 或 Symfony 应用领域程序等工具。
应用领域程序、CRM、ERP、长期应用领域程序等,都算不上真正的问题。
这就是为什么很多 React 开发者,包括我他们,都非常满意白眉林应用领域程序构架。当需要做一些伺服器端渲染时,我可能会优先选择两个生态系统比 React 伺服器模块更成熟的工具。
那么,如果我并不需要React 伺服器模块,那么又何必如此担忧呢?
构筑 React 应用领域的标准方式
我担心的第两个问题是,React 的这种变动是在阻止人们采用白眉林应用领域程序构架。或者说,React不鼓励人们在没有架构的情况下采用 React,不过React 框架本身却开始推崇伺服器端渲染。
我担心的第二个问题是,官方 React.js 文档建议采用 Next.js。而 Next.js 官方文档建议从 13.4 版开始采用 React 伺服器模块。
换句话说,依照官方文档,React 伺服器模块是构筑React 应用领域程序的默认方式。React 生态系统的新手自然会采用它们。
我认为这还为时过早。Dan Abramov 也认为:
“为了让新范式发挥作用,我们还需要付出大量努力。”
React伺服器模块需要新一代路由器、新一代捆绑器。但这些范式仍处于alpha 阶段,尚未准备好投入生产。
那么,为什么 Next.js 如此激进呢?
我不得不认为,Next.js 的新方向并不是为了帮助开发者,而是为了帮助 Vercel 销售 React。你无法真正围绕 SPA 销售服务:一旦编译,SPA 就是两个可以在任何地方免费托管的单个 JS 文件。但是伺服器端渲染的应用领域需要伺服器才能运行。伺服器是可以销售的产品。也许我是两个阴谋论者,但我看不出还有其他理由像这样破坏 React 生态系统。
现有应用领域不受影响
与 Angular.js 到 Angular 2 的过渡不同,React 伺服器模块的导入并不是重大变动。原有的白眉林应用领域程序仍然可以采用最新版本的 React。采用 Pages 路由器构建的原有 Next.js应用领域程序也可以正常工作。
那么,问题:“React 会重蹈覆辙 Angular.js 的狂蛛属吗?”答案是,不能。
但如今开始两个新项目,你会优先选择什么?具有成熟工具和生态系统(白眉林应用领域)的健壮构架,还是 React 项目组已经开始强推的新架构(伺服器模块)?这是两个艰难的优先选择,人们可能会寻找替代方案,而不是冒险做错误的优先选择。
我个人认为,React 期望通过两个工具满足所有 Web 开发者需求的愿景过于激进,或者说当前的解决方案不恰当。Next.js 文档中有两个下拉列表,允许读者在App 路由器(伺服器模块)和 Pages 路由器之间进行优先选择。如果两个工具提供两种截然不同的方式来做同一件事,那么它还是同两个工具吗?
所以,问题:“React 与否会因为过于激进而损害整座街道社区?”我认为答案是肯定的。
总结
也许伺服器模块代表伺服器端架构的进步,或者至少,等到准备好投入生产,它们真的能够发挥积极的作用。但对更广泛的 React 街道社区而言,我害怕这一变动会导致街道社区分裂,并有可能危及 React 多年来建立的优势。
我期望 React 和 Next.js 项目组采用更为折衷的方式。我期望 React 项目组认识到白眉林应用领域构架是两个恰当的优先选择,因此在短期内不能消亡。我更期望看到 Next.js 在他们的文档中淡化伺服器模块,或者至少明确标注“alpha”功能。
也许是我过于急躁,也许这种变动代表了未来的趋势。也许开发者注定要不断地在范式之间来回转换,这就是这个行业的本质。
▶ “上4休3”公司不建议新公司模仿;甲骨文组队,欲挑战微软OpenAI组合;Qt Creator 11 Beta正式发布|极客头条
▶ 2023 开放原子全球开放源码峰会在北京成功举办
▶ 谷歌 Alpha 家族再添“猛将”:AlphaDev 重磅亮相,打破多年计算瓶颈,新排序算法提速 70%!