escapeInject

Environment: server.

The escapeInject string template tag sanitizes HTML to prevent security risks commmonly called XSS injections.

If you use a UI framework Vike extension (vike-react/vike-vue/vike-solid), then you don't need to use escapeInject yourself as vike-react/vike-vue/vike-solid already sanitizes its HTML.

It's usually used by the onRenderHtml() hook.

// +onRenderHtml.js
// Environment: server
 
export { onRenderHtml }
 
import { escapeInject, dangerouslySkipEscape } from 'vike/server'
 
async function onRenderHtml() {
  const title = 'Hello<script src="https://devil.org/evil-code"></script>'
 
  // This HTML is safe thanks to `escapeInject` which sanitizes `title`
  return escapeInject`<!DOCTYPE html>
    <html>
      <head>
        <title>${title}</title>
      </head>
      <body>
        <!-- ... ->
      </body>
    </html>`
}

All strings, e.g. title above, are automatically sanitized (technically speaking: HTML-escaped) so that we can safely include untrusted strings such as user-generated text.

The dangerouslySkipEscape(str) function injects the string str as-is without sanitizing. We should use dangerouslySkipEscape() with a lot of caution and only for HTML strings that are guaranteed to be already sanitized. We usually use dangerouslySkipEscape() for including HTML generated by UI frameworks (React/Vue/...) as these are already sanitized. If we find ourselves using dangerouslySkipEscape() in other situations, we should be extra careful as we run into the risk of creating a security breach.

HTML Fragments

We can assemble the overall HTML document from several HTML fragments. For example, if we want some HTML parts to be included only for certain pages:

// +onRenderHtml.js
// Environment: server
 
import { escapeInject, dangerouslySkipEscape } from 'vike/server'
import { renderToHtml } from 'some-ui-framework'
 
export { onRenderHtml }
 
async function onRenderHtml(pageContext) {
  const description = pageContext.config.description
  const descriptionTag = !description ?
    '' :
    // We use `escapeInject` for an HTML fragment
    escapeInject`<meta name="description" content="${description}">`
 
  // We use `escapeInject` again for the overall HTML
  return escapeInject`<html>
    <head>
      ${descriptionTag}
    </head>
    <body>
      <div id="root">
        ${dangerouslySkipEscape(await renderToHtml(pageContext.Page))}
      </div>
    </body>
  </html>`
}

pageContext.config.description is a custom setting, see API > meta > Example: title and description.

Example: