escapeInject

Environment: Node.js

The escapeInject string template tag sanitizes HTML (to prevent XSS injections). It is usually used in the render() hook defined in .page.server.js.

// *.page.server.js
// Environment: Node.js

import { escapeInject, dangerouslySkipEscape } from 'vite-plugin-ssr'

export { render }

async function render() {
  const title = 'Hello<script src="https://devil.org/evil-code"></script>'
  const pageHtml = "<div>I'm already <b>sanitized</b>, e.g. by Vue/React</div>"

  // This HTML is safe thanks to the template tag `escapeInject` which sanitizes `title`
  return escapeInject`<!DOCTYPE html>
    <html>
      <head>
        <title>${title}</title>
      </head>
      <body>
        <div id="page-root">${dangerouslySkipEscape(pageHtml)}</div>
      </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 with caution only for HTML strings that are guaranteed to be already sanitized. We usually use it to include HTML generated by React/Vue/... as view frameworks already sanitize the HTML. If we find ourself 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 pieces of HTML fragments. For example, if we want some HTML parts to be included only for certain pages:

// _default.page.server.js
// Environment: Node.js

import { escapeInject, dangerouslySkipEscape } from 'vite-plugin-ssr'
import { renderToHtml } from 'some-view-framework'

export { render }

async function render(pageContext) {
  // We only include the `<meta name="description">` tag if the page has a description.
  // (Pages define `pageContext.documentProps.description` in their `onBeforeRender()` hook.)
  const description = pageContext.documentProps?.description
  let descriptionTag = ''
  if( description ) {
    // Note how we use the `escapeInject` string template tag for an HTML fragment
    descriptionTag = escapeInject`<meta name="description" content="${description}">`
  }

  // We use the `escapeInject` template tag again for the overall HTML and we can use
  // our `descriptionTag` HTML fragment.
  return escapeInject`<html>
    <head>
      ${descriptionTag}
    </head>
    <body>
      <div id="root">
        ${dangerouslySkipEscape(await renderToHtml(pageContext.Page))}
      </div>
    </body>
  </html>`
}

Example:

Edit this page