escapeInject

Environment: Node.js.

The escapeInject string template tag sanitizes HTML (to prevent so-called XSS injections security breaches).

It's usually used in the render() hook defined in renderer/_default.page.server.js.

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

export { render }

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

async function render() {
  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 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 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-ui-framework'

export { render }

async function render(pageContext) {
  const description = pageContext.exports.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.exports.description is a Custom Export.

Example: