此文档从技术角度阐述如何为 XenForo 引入基于 Popstate AJAX 的 SPA。之所以这么做,在产品角度的目的仅仅是为了优化用户的浏览体验,但在研发角度,则有力地说明了对于传统大型系统而言,重构前端代码以实现原有框架的单页化实际上具有一定的可能性。

单页应用概述​

单页应用支持——在 Popstate AJAX(以下简称 PJAX)原理上的取巧实现,相较于现代前端框架,需要多付出数倍的工作量。虽然后者具有严重疑似返祖迹象的 SSR(服务端渲染)技术支撑,但至少它们在网络请求上的区别,使得现代框架依然有信心坚称自己实现了真正的“关注点分离”。

但倘若我们稍微在全栈领域有所深耕,就会清楚地意识到:当设计模式(或者某种意义上的技术架构)带来的开发效益趋于饱和时,关注点的移动实际上是性能开销的移动——从服务端移动到了客户端。这种移动绝对是正收益的,因为仅仅从最浅薄的层次观察,客户端的计算能力至少有数码消费者在苦苦支撑;这就好比数十年前的游戏花费大量时间优化,而现如今则懂得都懂。好在因 SSR 而世风日下之时,React 出现了安全漏洞,但 U1S1,即使没有漏洞,SSR 也狗都不用。

服务器端​

服务器端生成的内容往往包含用于连接这些内容与前端 JavaScript 的信息。如果要连接的体量稍大,则直接使用内联<script>实现。

内置public模板helper_js_global负责完成该任务:

JavaScript
<script{{ $xf.request.isRocketLoaderDisabled() ? ' data-cfasync="false"' : ''}}>
    window.addEventListener('DOMContentLoaded', function() {
        XF.extendObject(true, XF.config, {
            // <!--[XF:js_global:xf_extend_start]-->
            userId: {$xf.visitor.user_id},
            enablePush: {{ $xf.options.enablePush ? 'true' : 'false' }},

            // ...

            refreshing: "{{ phrase('refreshing...')|escape('js') }}"
        });
    });
</script>