Tom 最近发表了对现代 web 的“二次思考”, 在前端世界掀起了一场风暴。你应该读读这篇文章或者起码读读摘要部分。我对于文章的很多内容持认可观点。
React 有很多优势:在现代交互界面...但是也有很多缺点。
对于静态的站点而言,在客户端运行 React 绝对是一种资源浪费。如果你的应用程序非常具有交互性,你必须避免使用 React ,这也是事实。人们普遍认为,如果你想要 60 fps 的动画效果,你可能需要绕过 React 更新反应周期,以一种更优雅的方式来实现( react-spring 就是干这事的)。但是,尽管所有这些 React 相关说法都是正确的,但在组件架构方面的观点我则不敢苟同。
用户会话的时间长得惊人: 我亲眼所见,有人可能一次就把你的网站打开几个星期。 因此,如果他们打开了“关于”页面,保持标签打开一周,然后请求主页,然后他们请求的主页由他们上周下载的索引包决定。这是一个非常奇怪和没有得到充分讨论的问题。
这是一个很好的观点,但问题没有真正得到解决,(正如 Tom 所承认的那样) 它实际上只是将一个一直存在的问题进行了夸张。我认为有一些解决方案,我们可以遍历 “index bundle” 路径,并且可以将网站版本存储在 cookie 中,然后用它来判断版本是否匹配。但是这么做,确实会额外花费一些精力。
这是你的创业公司的主页,有一个“注册”按钮,但是在 Java 加载之前,这个按钮什么也做不了。所以你需要做一些补偿措施。
虽然这样做很简单,但是这的确是一个问题。
<button class="sign-up" disabled= {!is_browser}> {is_browser ? 'Sign up' : 'Loading'} </button>
我不确定 React 风格的框架会怎么做,不管前端采用何种形式,这个问题一直都存在,除非你不用 JS。
你以前的轻量级应用程序服务器的确在承担相当多的任务,运行 React 和发送 API 请求来完成预渲染。
事实上,React 的服务器端渲染:构建组件树,然后序列化它—这就涉及到一些框架层面无法共享的性能开销,如将组建编译成拼接 SSR 字符串的函数,它的运行速度就会快很多。而且这些 API 请求必不可少,所以尽早响应这些请求就很有必要,尤其是当你的应用服务器和 API 服务器地理位置很近(甚至是同一个服务器)的时候。
理想的 API 具有通用和灵活的特点,你可以基于这些接口构建任意的 web 应用程序。这个想法很快破灭。
请去多读几遍 整个 API 部分。
除了一些小小的吹毛求疵之外,Tom 还指出了 web 开发中的一些现实问题。但我认为这篇文章得出了一个危险的结论。
让我们从剖析这个表述开始:
例如,我可以保证这个博客比任何一个 Gatsby 博客都要快(虽然我也非常喜欢 Gatsby 团队),因为 React 静态站点无法做到比非 React 静态站点更快。
恕我直言,我不认为 Gatsby 适合当作基准来比较。gatsby new my-site 在生产模式下启动完全静态的页面需要执行 266kb 的Java 文件; gatsbyjs.org 官网就得加载 808 kb 的 JS 文件。说实话,这样比没啥意义。
这是从 webpagetest.org/easy 处获取到的 Gatsby 首页的 lighthouse 结果。
我并不认可这个前提。当我点击 Tom 的不含 JS 的网站中的一个链接时,浏览器首先等待确认这是一个点击,而不是一个动画效果,然后发出请求,我们必须等待响应。如果我们使用具有客户端路由的框架编写网站,我们就可以在等待过程中做更多有趣的事情。我们可以根据用户可能与哪些事物进行交互的分析来做出明智的猜测,并据此执行一些预加载数据和处理。我们可以在用户第一次触碰到 (或者悬停) 链接时立即启动请求,而不是等待点击的确认 (最坏的情况是这样) ,我们已经加载了一些东西,如果他们以后真的点击它,这些东西就可以被利用起来。我们可以提供更好的视觉反馈,即加载正在进行,过渡效果等。而且我们通常不需要加载整个页面的内容,我们可以使用一点点 JSON,因为我们已经有了页面的 Java。这东西手工做起来极其困难。
除此之外,普通的静态网站并不够优雅。以页面切换为例。网络开发人员目前陷入了一种思维模式,即网页页面变化不和谐:点击链接,无论是通过客户端路由还是重新加载页面,整个页面都会被替换ー而本地应用开发人员则在另一个层面上思考:
技术进步不足以让互联网达到那个程度,还需要文化上的转变。但是,如果我们放弃目前的轨道,我们当然不可能达到那个目标。这正是 Tom 的意思。
我不知道还有哪个平台会要求你使用不同于后续交互逻辑的技术来编写初始化渲染的逻辑。这个想法听起来很愚蠢。但是在有着独特历史的网络上,这已经成为多年来的常态了ー我们用 PHP 或 Rails 或其他什么东西生成一些 HTML,然后在上面“撒上一些 jQuery”。
随着 Node 的出现,这种情况发生了改变。我们可以使用原生语言做服务器端渲染,可以与数据库通信,发展迅猛。
这种模式存在一些问题。Tom 指出了其中一些问题。他没有讨论的另一个主要问题是,服务器渲染的 SPA (单页面应用)模型通常会“hydrates” 整个初始页面,这种方式要求你复制大量数据(一次是在 HTML 中,一次是在传递到应用程序客户端版本的 JSON 二进制中,以产生完全相同的结果) ,并在用户开始与应用程序交互期间阻塞主线程。
但是我们可以解决这些问题。Next 是围绕(例如)在单个应用程序中混合静态和动态页面进行惊人的创新,这样你就可以获得纯静态模型的好处,而不会最终发现自己受到它的限制。Marko 进行智能组件级数据填充,我希望其他框架也能采用这种方法。Sapper 是 Svelte 开发的框架,它有一个明确的目标,即在不需要的页面外,不需要加载除(微型)路由之外的任何 JS 文件。
我想要的未来ー我看到的未来ー是一个拥有更多人 (包括设计师) 都可以使用的工具的未来,它可以在适当的情况下智能地在服务器和客户机之间迁移工作,让我们建立与用户体验本地化竞争的体验。如果将网站的一部分升级为“交互式”或者从“静态”升级为“动态” ,就不会涉及使用不同技术的不同团队之间的通信。我们只能通过遵循 Tom 批评的 Java 组件框架服务器渲染的 SPA (单页面应用模式)来实现这个目的。
虽然现代前端技术体系有缺陷,我们应该直面问题,而不是抛弃它。