Modern.js 作为以客户端为中心的开发框架,对服务端的定制能力较弱。而在有些开发场景下,需要定制特殊的服务端逻辑,例如用户鉴权、请求预处理、添加页面渲染骨架等。
一些开发者可能会有疑惑,Modern.js 已经提供了 BFF 能力,为什么还需要自定义 Web Server。
因为在默认情况下,页面路由并不会经过 BFF,它没有办法为页面访问提供服务端的定制逻辑。之所以这样设计,是因为我们不希望控制页面的服务与 BFF 服务绑定在一起,避免 BFF 的框架限制页面的部署方式。例如将页面与 BFF 分开托管、将页面服务部署到非 Node 的环境上,或是针对部署平台做定制等。
出于上述原因,Modern.js 提供了三种方式,让项目可以在根据需求,渐进式的定制服务端能力。
三种扩展方式无法同时工作,开发者需要根据场景选择合适的方式。
第一种方式是通过 Modern.js 提供的服务端运行时 API,在特定的生命周期对服务端进行定制。提供这种方式的目的是在部分情况下,开发者并不需要控制完整的 Web Server,只需要添加服务端逻辑即可。
这种方式无法控制完整的 Web Server,并且扩展逻辑只在请求页面时生效。因此,它适用于服务端逻辑相对简单,不希望额外创建 BFF 或者 BFF 和页面无需公用服务端逻辑场景。
可以在项目根目录执行 pnpm run new
命令,开启「自定义 Web Serve」功能:
执行命令后,在 modern.config.ts
中注册 @modern-js/plugin-server
插件:
开启功能后,项目目录下会自动创建 server/index.ts
文件,可以在这个文件中编写自定义逻辑。Modern.js 提供了 Hook 与 Middleware 两类 API 来扩展 Web Server。
Modern.js 提供的 Hook 用于控制 Web Server 中的内置逻辑,所有的页面请求都会经过 Hook。
目前提供了两种 Hook,分别是 AfterMatch
和 AfterRender
,可以用于修改渲染结果。可以在 server/index.ts
中这样写:
项目在使用 Hook 时,应该有以下最佳实践:
详细 API 和更多用法可以查看 Hook。
对于某些项目,可能在服务端有更多的需求,Modern.js 提供了 Middleware 为 Web Server 添加前置中间件。它只能运行在 Node 环境下,因此如果项目被部署到其他环境中,如 Worker 环境,则不可以使用 Middleware。
下一个大版本,Modern.js 将会使用新 Middleware 来替代该写法。
推荐使用 UnstableMiddleware 处理页面请求。
Modern.js 默认提供了一套 API 供项目使用:
详细 API 和更多用法可以查看 Middleware。
项目在使用 Middleware 时,应该有以下最佳实践:
总的来说,CSR 项目中,使用 Hook 基本能满足简单场景的所有需求。SSR 项目中,可以使用 Middleware 做更复杂的 Node 扩展。
Modern.js 将提供新 Middleware 为 Web Server 添加前置中间件,支持在处理页面的前后执行自定义逻辑。
详细 API 和更多用法查看 UnstableMiddleware
第二种方式,是利用 BFF 来托管页面渲染,这种方式下,所有的请求都会先打到 BFF 的服务。
因为这种方式可以通过 BFF 统一控制所有请求的服务端逻辑。因此,它适用于服务端逻辑复杂,BFF 和页面需要公用服务端逻辑的场景。但它整体还是依托于 Modern.js 的 Web Server 运行,无法将逻辑运行在已有的服务上。
使用这种方式,我们需要先通过 pnpm new
开启「BFF」功能。然后在配置文件中添加 bff.enableHandleWeb
配置:
当该值设置为 true
时,页面请求流量也会经过 BFF,并且 Modern.js 内置的页面渲染的逻辑默认会作为 BFF 服务的最后一个中间件运行。
敬请期待