假期回来后,有人开玩笑说 JavaScript 决定完全转向服务器端。 我认为这源于
- Basecamp 团队发布了 Hotwire,这看起来像是对多种技术的营销策略。 他们说“通过网络传输 HTML”,这意味着它让服务器生成和提供 HTML,并将客户端 JavaScript 留给只有客户端 JavaScript 才能做的事情。
- React 团队 介绍零包大小 React 服务器组件,我相信这是核心项目迈向服务器端一切的第一步。
我非常喜欢一些营销炒作,但值得注意的是,这些只是对已经成熟(我敢说老)想法的新颖诠释。
Turbo(“Hotwire 的核心”)是 Turbolinks 的进化版本,它是一个非常简单的基本理念:拦截内部链接上的点击。 浏览器不再执行完整的页面刷新,而是fetch
新页面的内容,将其放置到位,并History.pushState()
URL。 现在您有了单页应用程序的感觉,但您不必构建 SPA。 如果你已经使用 ERB 模板在 Rails 中构建了你的应用程序,这非常方便。
但这实际上效率高吗? 好吧,到目前为止它并不特别受欢迎。 之前的想法是网络是瓶颈,所以让我们通过网络发送尽可能少的内容。 “尽可能少”通常转化为 JSON。 如果你在客户端获得 JSON,现在你需要在客户端使用模板系统将其转换为可用的 DOM。 使用这种技术,你要付出两方面的代价:1) 加载客户端库 2) 数据到 DOM 的处理。 如果你通过网络发送“HTML”,你就不需要支付这两项费用(更快),但理论上会通过网络发送更庞大的有效载荷(更慢),这假设 HTML 比 JSON 更重,这是...有待商榷的。
所以...视情况而定。 这取决于有效载荷的大小以及预期对它们执行的操作。
你会期待 React 的观点是:一定要使用客户端。 但对于新的 服务器端组件预览,情况并非如此。 视频非常清楚地表明:“在服务器上渲染”组件更快,尤其是在嵌套组件情况下,其中许多组件负责获取自己的数据。 那么通过网络传输什么呢? 是 DOM 就绪的 HTML 吗? 不是在这里。 从视频中可以看出,网络响应是某种专有格式¹,它描述了 React 组件。 这似乎很重要,因为它意味着客户端 JavaScript 包根本不包含该组件,并且状态²可以来回传递。 Lauren Tan 在视频中也明确表示:这有点像 SSR,但与 Next.js 今天使用 SSR 的方式不同。 关键是让明天的 Next.js 变得更好。
所以:服务器。 他们只是擅长做某些事情(一位正在 WordPress 博客上打字的人说)。 确实似乎有一些趋势朝着在客户端上做更少的事情发展,我认为我们大多数人都会同意,最近客户端承担了太多责任,这导致了资产大小不断增长。
在我们继续前进的同时,让我们将这些服务器推向边缘。
- 这是一种专有格式。 我被告知它类似于“带孔的 JSON”,即用空格和换行符分隔的 JSON 块。 但是,虽然格式很重要,因为你可能需要检查网络请求以进行调试,但这毕竟是 React 与 React 之间的通信,它不是一个公开的 API,格式在其中不会很重要。
- 传递的主要“状态”类似于当前路由。 我被告知你尽可能少地传递给服务器。 服务器不保留任何状态。
哦,是的。 请。 你们花了 10 年才意识到我们走错了路,但万岁。
我反对将所有东西都迁移到客户端 js 的整个举措,原因更加根本,比如渐进增强,但无论什么能阻止这种疯狂,我都会支持。
(而且不,请不要让下一个炒作成为 CDN EVERYTHING!!1)
你不喜欢 CDN 吗?
另一方面,如果你需要构建一个非 Web 客户端(例如移动端),你可能已经失去了所有这些方便的 API 来获取数据,因为你没有构建它们来支持你的 SPA。
这并不完全正确,对吧? 我认为在设计良好的系统中,你应该能够插入一些控制器来利用现有服务来提供 API。
这些 SSR 也在使用服务器上的同一个 API,所以它仍然完好无损……
我想要的是
基于组件的开发,使用 JSX(和 TypeScript)
静态/服务器生成的 HTML
在客户端动态重用组件
只将动态组件发送到浏览器(这是 Next/Gatsby 等失败的地方,它们将静态内容发送两次,一次作为 HTML,一次作为 JS/JSON,然后承担重新水化的额外成本); 这方面有很多很好的工作,包括我现在正在使用的 Microsite(并且今天开始为其做贡献); 服务器组件也可能实现这一点
构建工具,通过提供适当的配置 API 使静态/动态区分成为一等概念
动态客户端实现,通过提供适当的运行时 API 使静态/动态区分成为一等概念
编译器,可以使用静态分析自动执行静态/动态区分; Marko 已经在做所有这些,除了支持 JSX
html {
服务器:js
}
你们都应该试试 AureliaJs。
我喜欢 html、css 和 JavaScript。 我相信它们可以完成任何大多数用户界面应用程序。
也就是说,管理状态、进行单向或双向绑定、简单路由等并不容易。
Aurelia 就在这里,它提供了这些功能,以 KISS 的方式。 我实际上正在使用 html、css 和 js,而 Aurelia 并没有妨碍我,只是非常方便,同时让我保持了我喜欢做的事情的精神。(没有 html 在 js 中的奇怪东西,易于管理状态,漂亮的组件)。
除此之外,如果你喜欢,你可以轻松地使用 pug、sass 和 typescript,轻松易行。
你没有使用 Aurelia,它们不想占用空间,它们想消失,让你做你喜欢的事情。
https://aurelia.io/
(它也是开源的,没有 GAFAM 或者任何大科技公司参与 ;) )。
让网络保持开放、透明和美丽
你假设渲染在服务器上更快,只有在你那里有足够的计算资源时才成立,但情况可能并非如此。
如果所有计算都在那里完成,原始服务器可能会严重过载。 所以答案必须是边缘服务器。 但是,你必须使用一个好的 CDN 来实现良好的边缘分发,然后你必须使用来自 CDN 提供商本身的边缘服务器。
假设是 Cloudflare。 所以边缘服务器必须是 Cloudflare worker。 CF 声称它们可以扩展,这很好。 但是,它们扩展是有价格的。 如果你超过了每日或每月限制,你需要按请求付费,尽管我想这已经是最便宜的了。
让我们现实一点。 Cloudflare 不是魔法。 它在边缘运行自己的集群,并且有自己的容量。 如果每个网站都在上面运行完全的服务器端渲染,它永远不会足够。
但是,如果你纯粹在客户端进行操作,你可能会让你的前端保持纯粹的静态。 服务器上没有进行计算意味着你的原始服务器和边缘服务器更快乐,因此你更快乐,最终你的用户也更快乐。
还有另一件事是边缘服务器很慢。 与用户设备相比,Cloudflare worker 严格来说很慢。 你可能有一个多核的、不错的 CPU,可能还有一个可用的 GPU,以及足够的内存:尽管它并非全部为你使用。 但是对于边缘服务器,好吧,你知道它的情况有多糟糕。
我发现恰恰相反。
@Chris Coyier
对于 I/O 密集型任务,我同意 CF worker 可能更快,因为它们可以从 CF 缓存和 CF kv 中更快地获取数据。 而且它们通常可以更快地访问原始服务器。
但是对于计算密集型任务,用户设备更快,你甚至无法有效地使用 CF worker 进行计算,因为它们只有 128MB 的内存和 50 毫秒的延迟。
但是服务器端渲染也有它自己的缺点
* 如果你不进行客户端渲染,你的第一次加载速度不慢,但第二次加载速度不快。
* 如果你两种方式都进行,你的第一次加载速度很快,第二次加载速度也很快,但你在第一次加载时下载了所有内容两次。
使用
link: preload
(以及 link[rel=”preload”] 和缓存,比如 Service Worker),而不是所有这些 SSR,你就有* 快速首次加载,与您的 SSR 一样快,如果您可以进行服务器推送,否则只需要一次额外的往返行程。
* 快速第二次加载,比任何没有预加载的方式都快。
* 保持您的下载量最小。
* 并且,您将计算保留在客户端:您支付的更少,并且您的用户不会介意 128MB-50ms 的延迟。