Intro

There are some key data types, which could be imported from vise-ssr package, vital to the development of app, server and plugin development.

RenderContext

RenderContext is mainly used for storing and passing data between Vise hooks. Tapped functions of Vise hooks can store there data in the context, or read data in the context.

In a typical scenario,

  • requestResolved: Parsing user info in the cookie, put anything may be needed in later hooks such as user’s id, or put user into a specific AB-test bucket, storing that data in RenderContext.extra
  • beforeRender: Loading data required by the page from certain APIs, generating store’s initState, storing it in RenderContext.meta.initState
  • render: Reading initState and passing it to UI library’s server render function as SSRContext. Writing SSRContext’s data changed during the render back to the context, such as the page title: RenderContext.meta.title
  • afterRender: Read data set by previous hooks, generating the final render result
  • beforeRender: Read data set by previous hooks, generating the final HTTP Response

RenderContextMeta

type RenderContextMeta = Partial<{
  // page title
  title: string,
  // should SSR result be cached
  cache: boolean,
  // initState used for store
  initState: JSONObject,
  // url in HTTP request passed around hooks do not have
  // routerBase prefix
  routerBase: string,
  // UI library app rendered as string
  // be careful of hydration mismatch
  app: string,
  // HTML template
  template: string,
  // preload link as string for the rendered page
  preloadLinks: string,
}>;

RenderContext.meta is used for storing data defined by Vise. It has following properties:

  • title: UI library can set page title here during render.
  • cache: Indicate whether the render result is cacheable, should be set to false after render failed.
  • initState: Preloaded state of UI library’s store. If strictInitState in Vise config is set to true, all changes to the state during render will be ignored.
  • routerBase: Url in the RenderContext.request do NOT have routerBase prefix. Sometimes apps may want to access it in Vise hooks.
  • app: UI library render result string.
  • template: Template string used to generate the whole HTML page. HTML could be regenerated by calling refillRenderResult after changing the template.
  • preloadLinks: HTML tags of resources needed to be preloaded.

RenderContext Definition

// data pass to SSRContext
type SsrContext = {
  meta: RenderContextMeta,
  extra: JSONObject,
};

// SSR Render Context, used for store the HTTP request
// and the data shared between multiple hooks
type RenderContext = {
  request: HTTPRequest,
  error?: RenderError, // hooks should put their error here when render failed
} & SsrContext;

RenderResult

Result of an SSR, with 4 possibilities:

  • A successful render
  • A failed render
  • A custom render
  • A cache hit
type RenderResultBase = {
  context: RenderContext,
  // renderer is used for tracing
  renderBy: string,
};

export type SuccessRenderResult = RenderResultBase & {
  // this is a successful new rendering
  type: 'render',
  // complete html generated from template and rendered app's html
  html: string,
  // afterRender hooks could use it to update cache
  cacheInfo?: CacheInfo,
};

export type RenderResult = (RenderResultBase & ({
  type: 'error',
  // HTTP response of the render error could by generated from the error details
  // eg: displaying the error or redirect to another url
  error: RenderError,
} | {
  // this request is intercepted in receiveRequest hook, SSR is bypassed
  // generate HTTP response with custom logic
  type: 'receiveRequest',
} | {
  // cache hit, no real render happens
  type: 'hitCache',
  content: string,
  cacheInfo: CacheInfo,
})) | SuccessRenderResult;

ViseHooks

This is the exported type of file server-hooks.ts with logic of custom tapped functions of Vise hooks in the whole lifecycle. Multiple callbacks and Vise hooks plugins are supported.

// defined callbacks of all Vise hooks
export type HookCallback = //...;

// added array of callbacks and callback calling timing enforce support
export type HookCallbackConfig = {
  [K in HookNames]?: ArrayOrSingle<HookCallback[K]> | ArrayOrSingle<{
    callback: HookCallback[K],
    // enforce the execution order of waterfall type callbacks
    // execution order: pre => default (without enforce) => post
    enforce?: 'pre' | 'post',
  }>;
};

// exported type of server-hooks.ts
// can config callbacks for hooks and vise hook plugin
export type ViseHooks = HookCallbackConfig & {
  appName: string,
  plugins?: Array<VisePlugin>,
};

VisePlugin

The type of Vise Hook Plugin, which can be used in server-hooks.ts. It’s basically a group of related vise hook callbacks.

export type VisePlugin = {
  /**
   * Plugin should have the same name in setting as the corresponding npm package name
   * Plugin name should start with 'vise-plugin-',
   * unless it's an internal plugin.
   * Plugin name should only contain lowercase letter, number and hyphens and start with letter
   * internal: `vise:${name}`
   * external: `vise-plugin-${name}`
   */
  name: string,
  hooks: HookCallbackConfig,
};

CacheInfo

Cache related type used by hooks such as beforeUseCache, findCache, hitCache.

export type CacheInfo = {
  // cache key generated from HTTP request, must be unique
  key: string,
  // unix timestamp expire time
  expire: number,
  // use expired data first then update it
  stale: boolean,
  context: RenderContext,
};