Hook

Used to extend Modern.js built-in Web Server, all page requests are handled by these hooks.

WARNING

It is recommended to use UnstableMiddleware to handle page requests.

NOTE

For more detail, see Extend Web Server.

Usage

import { AfterMatchHook, AfterRenderHook } from '@modern-js/runtime/server';

export const afterMatch: AfterMatchHook = (context, next) => {};
export const afterRender: AfterRenderHook = (context, next) => {};
INFO

Before using this API, please execute pnpm run new to create a new "Custom Web Server" source code directory.

pnpm run new
? Please select the operation you want: Create Elements
? Please select the type of element to create: New "Custom Web Server" source code directory

Function Signature

type HookContext = {
  response: {
    set: (key: string, value: string) => void;
    status: (code: number) => void;
    getStatus: () => number;
    cookies: {
      set: (key: string, value: string, options?: any) => void;
      clear: () => void;
    };
    raw: (
      body: string,
      { status, headers }: { status: number; headers: Record<string, any> },
    ) => void;
  };
  request: {
    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;

different Hooks additionally provide different contexts. Currently Modern.js support AfterMatch and AfterRender.

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;
  };
};

Input

  • context: Hook context.
    • response: provides a series of methods to process the response.
    • request: provides a series of methods to get request info.
    • router: provides methods on routing.
    • template: provides methods on content.
  • next: call next listener (not affect the server process, only current hook).

Example

Redirect

Redirect to pages outside the site, for example to login page:

import type { AfterMatch } from '@modern-js/runtime/server';

export const afterMatch: AfterMatch = async (ctx, next) => {
  ctx.router.redirect('https://website.com/login', 302);
};

Rewrite

Rewrite to pages of the current site, for example, the same route returns pages that are adapted to different UA:

import type { AfterMatch } from '@modern-js/runtime/server';

export const afterMatch: AfterMatch = async (ctx, next) => {
  ctx.router.rewrite('mobile');
};

HTML Inject

Inject some HTML content to the page, such as scripts, page skeletons, etc.:

import type { AfterRender } from '@modern-js/runtime/server';

export const afterRender: AfterRenderHook = (context, next) => {
  ctx.template.prependBody('<div>Footer</div>');
};