Como usar SSR com Vue 3

Oct 07 2020

Eu tenho um aplicativo Vue 2 funcionando com renderização do lado do servidor. Agora estou tentando atualizar para o Vue 3, mas estou preso na parte SSR porque o pacote vue-server-renderer gera o seguinte erro:

Vue packages version mismatch: - [email protected] - [email protected] This may cause things to work incorrectly. Make sure to use the same version for both.

Mas não há versão 3.0.0 para vue-server-renderer ...

Pesquisando no Google, encontrei este problema no repositório vue-next: https://github.com/vuejs/vue-next/issues/1327

Mas para mim ainda não está claro como alcançar o SSR com a versão 3 do vue. Já é possível? Existe um exemplo de como usar SSR com Vue 3?

Respostas

11 UliKrause Nov 01 2020 at 11:43

Vue-server-renderer só pode ser usado com vue versão 2. Uma das grandes mudanças com a versão 3 é que agora ele tem suporte SSR integrado.

Então, em vez de usar o renderizador de servidor vue-2.0, agora você só precisa usar o vue createSSRApp. No servidor, para renderizar o aplicativo assim criado em uma string que você pode enviar ao navegador, você deve usar o renderToStringmétodo do qual pode importar @vue/server-renderer(observe que você deve instalar este pacote separadamente).

Como um exemplo superbásico (sem bundler ou qualquer coisa), isso seria parecido com este:

const express = require('express');
const { createSSRApp } = require('vue');
const { renderToString } = require('@vue/server-renderer');

const app = express();

const example= {
  template: `
    <div>
      Hello World
    </div>`,
};

function renderVueApp(req, res) {
  const vueApp = createSSRApp(example);

  (async () => {
    const html = await renderToString(vueApp);

    res.send(`
      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <script src="https://unpkg.com/vue@next"></script>
          <title>About blank</title>
        </head>
        <body>
          <div id="app">${html}</div> <script> const example = { template: '<div>Hello World</div>}; Vue.createSSRApp(example).mount('#app', true); </script> </body> </html> `); })(); } app.get('/', renderVueApp); const port = process.env.PORT || 8080; app.listen(port, () => console.log(`Server started at localhost:${port}. Press ctrl+c to quit.`)
);

No front-end você deixa o vue assumir a marcação do servidor, ou seja, você cria e monta o aplicativo no modo de hidratação.

O renderizador de pacote que você referiu em sua pergunta foi mais ou menos extraído do renderizador de servidor vue-2.0. Para usá-lo, você terá que usar o plugin do cliente e o plugin do servidor do pacote vue-2.0 server-renderer e conectá-los ao processo do webpack para obter o pacote do servidor e o manifesto do cliente.

Observe que, com esta configuração, o renderizador de pacote injetará apenas scripts de entrada / iniciais com rel = "preload". No momento, o 'novo' vue-loader não injetará nenhuma lógica de registro de componente nos componentes (como o 'antigo' vue loader faz). Ainda assim, vue-bundle-renderer pode e irá injetar blocos assíncronos com rel = "preload", desde que eles sejam referenciados em ssrContext._registeredComponents. Portanto, se você precisar desse recurso em seu aplicativo, terá que escrever essa lógica sozinho.

Claro, essa é uma maneira de fazer isso. Tenho certeza de que há muito mais estradas que levam ao mesmo destino.

Eu escrevi uma versão vue3 do clone do vue2 hackernews, que usa todas as coisas descritas / mencionadas.

Você pode encontrá-lo aqui: https://github.com/raukaute/vue-hackernews-3.0