Tool integration (more)

Feel free to reach out if you run into any issues integrating a tool.

Vanilla UI tools

To initialize UI vanilla tools (jQuery, tooltips, ...) you can use the onHydrationEnd() hook.

// pages/+onHydrationEnd.js
 
export default () => {
  // Initializing vanilla JS component libraries, for example tooltips, after hydration.
  tooltip.init(document.querySelectorAll('.tooltip'))
  // Or some vanilla JS modal library
  $('.my-modals').modal()
}

Analytics

To inject external <script> tags, you can use:

You can use the +client.js file to initialize analytics code.

// pages/+client.js
 
someAnalyticsLibrary.init(/* ... */)

That way you can install tools such as Google Analytics, Plausible, or Segment.

You can also load and/or initialize analytics code only after the hydration ends by using the +onHydrationEnd hook.

Component libraries

Some compnent libraries need initialization, most notably vanilla component libraries such as Bootstrap.

To initialize code, you can use

To inject external scripts, you can use:

Examples:

Data fetching

Instead of using the +data hook, you can use tools to fetch the page's initial data.

🧠

The following explains how to integrate tools for fetching initial data. Instead of manually integrating tools yourself, we generally recommend using Vike extensions such as vike-react-apollo or vike-vue-query.

⚠️ We recommend using this advanced capability, which can be complex, only if you have a clear reason for avoiding potentially simpler options.

Some data-fetching tools enable you to fetch a page's initial data on a component-level instead of using the page-level Vike hook data()

On a high-level, the integration works like this:

  1. The initial data of a component is fetched while server-side rendering the component.
  2. The initial data is serialized and passed to the client. (So that the client uses the exact same data, avoiding double-fetching and hydration mismatches.)

If SSR is disabled, then the data is only fetched on the client-side. (The component's data is fetched where the component is loaded and executed.)

Some tools provide utilities to integrate more or less automatically. For example Apollo GraphQL provides many utilities to make integration easy.

A fully manual integration can be done as follows:

  1. Determine the initial data on the server side (after SSR) and make it available as pageContext.dataInitial.

    You can configure/initialize the tool's client at onBeforeRenderHtml():

    // pages/+onBeforeRenderHtml.js
     
    import { init } from 'awesome-data-tool'
     
    export function onBeforeRenderHtml(pageContext) {
      pageContext.dataClient = init({ someConfiguration: 'value' })
    }

    You can determine the initially fetched data at onAfterRenderHtml():

    // pages/+onAfterRenderHtml.js
     
    export function onAfterRenderHtml(pageContext) {
      pageContext.dataInitial = pageContext.dataClient.getFetchedData()
    }

    If you use React then you may also need to use +Wrapper:

    // pages/+Wrapper.jsx
     
    import { Provider } from 'awesome-data-tool/react'
    import { usePageContext } from 'vike-react/usePageContext'
     
    export function Wrapper({ children }) {
      const pageContext = usePageContext()
      return <Provider client={pageContext.dataClient}>{children}</Provider>
    }
  2. Make pageContext.dataInitial available to the client-side by using passToClient.

  3. On the client-side, initialize with pageContext.dataInitial.

    Typically at onBeforeRenderClient():

    // pages/+onBeforeRenderClient.js
     
    import { initClient } from 'awesome-data-tool'
     
    export function onBeforeRenderClient(pageContext) {
      pageContext.dataClient = initClient({ data: pageContext.initialData })
    }

See also:

Service workers

You can use the +client.js file to initialize service workers.

// pages/+client.js
 
// Initializing a Service Worker
navigator.serviceWorker.register(/* ... */)

Without vike-{react,vue,solid}

You can manually integrate React/Vue/Solid (or any other UI framework) yourself:

You gain control not only over how React/Vue/Solid is integrated, but also how React/Vue/Solid tools are integrated.

// /renderer/+onRenderHtml.js
// Environment: server
 
import { escapeInject, dangerouslySkipEscape } from 'vike/server'
// This can be any UI framework (React, Vue, Solid, Svelte, ...)
import renderToHtml from 'some-ui-framework'
 
export { onRenderHtml }
 
async function onRenderHtml(pageContext) {
  // `Page` is the `export { Page }` of our +Page.js files;
  // Vike doesn't do anything with `Page` and just makes it available as
  // `pageContext.Page`; we can export any `Page` value we want and do whatever we want with it.
  const { Page } = pageContext
 
  // We control how we use our UI framework to render our pages to HTML
  const pageHtml = await renderToHtml(Page)
 
  // We control the entire HTML
  return escapeInject`<html>
    <body>
      <head>
        <!-- Some libraries recommend loading code from a CDN -->
        <script src="https://cdn.example.com/some-library/3.3.7/lib.min.js"></script>
      </head>
      <div id="root">
        ${dangerouslySkipEscape(pageHtml)}
      </div>
    </body>
  </html>`
}
// /renderer/+onRenderClient.js
// Environment: browser
 
export { onRenderClient }
 
import { hydrateDom } from 'some-ui-framework'
 
async function onRenderClient(pageContext) {
  // Here we can integrate performance measurement tools, e.g. to measure hydration performance
  const { Page } = pageContext
  // We control how our pages are hydrated
  await hydrateDom(Page)
}

See:

Since you control how your pages are rendered, you can use any tool you want without any restrictions.

  • Any UI framework (React 16, React 17, Vue 2, Vue 3, petite-vue, Svelte, Solid, Preact, ...)
  • Any UI library (Vuex, Redux, Pinia, Relay, Apollo GraphQL, Recoil, ...)
  • Any CSS framework (Tailwind CSS, Bulma, Bootstrap, Material Design, ...)
  • Any client-side library (Vanilla JS component libraries, Bugsnag, Sentry, jQuery, Google Analytics, ...)
  • Any browser technology (Service Workers, PWA, ...)
  • Etc.

The Vike extensions vike-react/vike-vue/vike-solid aim to be almost as flexible. If you reach a limitation you believe is caused by vike-{react,vue,solid} then reach out before considering going for a manual integration.

See also