Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use SSR with Vue 3

I have a working Vue 2 app with server side rendering. Now I'm trying to upgrade to Vue 3 but stuck on the SSR part cuz the vue-server-renderer package throws the following error:

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

But there is no version 3.0.0 for vue-server-renderer...

With googling I found this issue on the vue-next repository: https://github.com/vuejs/vue-next/issues/1327

But for me it is still unclear how to achieve SSR with version 3 of vue. Is it already possible? Is there an example how to use SSR with Vue 3?

like image 660
Nio Avatar asked Oct 07 '20 07:10

Nio


People also ask

Does Vue use SSR?

Quasar is a complete Vue-based solution that allows you to target SPA, SSR, PWA, mobile app, desktop app, and browser extension all using one codebase.

What is SSR in Vue?

Server-side rendering (SSR), is the ability of an application to contribute by displaying the web-page on the server instead of rendering it in the browser. Server-side sends a fully rendered page to the client; the client's JavaScript bundle takes over which then allows the Vue.

Is Vue client-side or server-side?

Vue is primarily client side framework - rendering is done by JS running in the client's browser. Your app has (usually) only one index. html .

What is the difference between SPA and SSR?

In general, SSG sites and SSR sites are faster than SPAs in terms of loading content. SPAs, as mentioned earlier, need to download the JavaScript for the app before they can display content. However, in some cases, SSG and SSR can be slower.


1 Answers

Vue-server-renderer can only be used with vue version 2. One of the big changes with version 3 is that it now has SSR support baked in.

So instead of using the vue-2.0 server-renderer you now just have to use vue's createSSRApp. On the server, to render the thus created app to a string that you can send to the browser you'd use renderToString method which you can import from @vue/server-renderer (note that you have to install this package seperately).

As a super basic (without bundler or anything) example this would look sth like this:

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.`)
);

In the front-end you let vue take over the markup from the server, i.e. you create and mount the app in hydration mode.

The bundle renderer you referenced in your question is more or less just extracted from the vue-2.0 server-renderer. In order to use it, you will have to use the client-plugin and server-plugin from the vue-2.0 server-renderer package and plug them into your webpack process to get the server-bundle and the client manifest.

Note that with this setup, the bundle renderer will only inject entry/initial scripts with rel="preload". Right now, the 'new' vue-loader won't inject any component registration logic into components (like the 'old' vue loader does). Still, vue-bundle-renderer can and will inject async chunks with rel="preload", as long as they are referenced in ssrContext._registeredComponents. So if you need this feature in your app, you will have to write up that logic yourself.

Of course, this is one way to do it. I'm sure there plenty more roads that lead to the same destination.

I wrote up a vue3 version of the vue2 hackernews clone, which uses all the described/ mentioned things.

You can find it here: https://github.com/raukaute/vue-hackernews-3.0

like image 114
Uli Krause Avatar answered Oct 24 '22 21:10

Uli Krause