用于拓展 Modern.js 内置的 Web Server,所有的页面请求都会经过 Hook。
更多内容可以查看自定义 Web Server。
import { AfterMatchHook, AfterRenderHook } from '@modern-js/runtime/server';
export const afterMatch: AfterMatchHook = (context, next) => {};
export const afterRender: AfterRenderHook = (context, next) => {};
使用该 API 前,请先执行 pnpm run new
新建「自定义 Web Serve」源码目录。
pnpm run new
? 请选择你想要的操作 创建工程元素
? 新建「自定义 Web Server」源码目录
type HookContext = {
response: {
set: (key: string, value: string) => void;
status: (code: number) => void;
cookies: {
set: (key: string, value: string, options?: any) => void;
clear: () => void;
};
raw: (
body: string,
{ status, headers }: { status: number; headers: Record<string, any> },
) => void;
};
request: {
url: string;
host: string;
pathname: string;
query: Record<string, any>;
cookie: string;
cookies: {
get: (key: string) => string;
};
headers: IncomingHttpHeaders;
};
};
function Hook(context: HookContext, next: NextFunction): Promsie<void> | void;
另外,不同 Hook 额外提供了不同的上下文。目前 Modern.js 支持 AfterMatch
和 AfterRender
两个 Hook。
type AfterMatchContext = HookContext & {
router: {
redirect: (url: string, status: number) => void;
rewrite: (entry: string) => void;
};
};
type AfterRenderContext = {
template: {
get: () => string;
set: (html: string) => void;
prependHead: (fragment: string) => void;
appendHead: (fragment: string) => void;
prependBody: (fragment: string) => void;
appendBody: (fragment: string) => void;
};
};
context
:提供当前 Hook 上下文。
response
:提供一系列处理响应的操作request
:提供一系列获取请求信息的操作router
:提供对响应路由的快捷操作template
:提供对响应内容的快捷操作next
:执行当前 Hook 的下一个监听函数(不影响整体服务端流程)。将页面重定向到站点外的页面,例如跳转到统一登录页:
import type { AfterMatch } from '@modern-js/runtime/server';
export const afterMatch: AfterMatch = async (ctx, next) => {
ctx.router.redirect('https://website.com/login', 302);
};
将页面重写到当前站点的其他页面,例如同一个路由根据 UA 返回适配不同端的页面:
import type { AfterMatch } from '@modern-js/runtime/server';
export const afterMatch: AfterMatch = async (ctx, next) => {
ctx.router.rewrite('mobile');
};
为页面注入某些与渲染主体无关的 HTML 内容,如脚本、页面骨架等:
import type { AfterRender } from '@modern-js/runtime/server';
export const afterRender: AfterRenderHook = (context, next) => {
ctx.template.prependBody('<div>Footer</div>');
};