Search code examples
expressvue.jsvuejs2nestjsserver-side-rendering

Vue + Express(NestJS) Impossible task, You are using the runtime-only build of Vue where


It's making it impossible for me to add Vue as a view system to a framework called Nest with Express.

I didn't think that adapting Vue was so complicated. That's why I'm here so that you can guide me on the right path and I won't use Vue directly.

Fist the error:

    [Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
(found in <Root>)

app.controller.ts

import { Controller, Get, Render, Response } from '@nestjs/common';
import { createRenderer } from 'vue-server-renderer';
import { createApp } from './app';
import HelloComponent from './components/Hello';
const context = {data: {}, view: '', componets: {} };

@Controller()
export class AppController {
  @Get()
  getHello(@Response() res): any {
    context.data = { message: 'Esto es un nuevo mensaje 2' };
    context.componets = { 'hello' : HelloComponent };
    const app = createApp(context);
    const renderer = createRenderer();
    renderer.renderToString(app, (err, html) => {
      res.end(html);
    });
  }
}

import { createApp } from './app';

import Vue from 'vue';

export function createApp(context: any) {
  return new Vue({
    data: context.data,
    template: fs.readFileSync('./index.html', 'utf-8'),
    components: context.components,
  }).$mount('#app');
}

I try is to have a base template and then add the components for each controller or route with NestJS.

I don't know if this is possible and if I'm forced to use Webpack, since I'm not currently using it.

Thanks!


Solution

  • Vue launched an entire site to walk you through getting your server side rendering up and running. It is NOT the same process that is outlined at https://vuejs.org.

    Complete information can be found at: https://ssr.vuejs.org/ and is referenced in the main guide about halfway down the sidebar navigation under the heading serverside rendering https://v2.vuejs.org/v2/guide/ssr.html

    Here is the gist of it to get you started:

    npm install express --save
    
    npm install vue vue-server-renderer --save
    

    Integrating with your server example

    const Vue = require('vue')
    const server = require('express')()
    const renderer = require('vue-server-renderer').createRenderer()
    
    server.get('*', (req, res) => {
      const app = new Vue({
        data: {
          url: req.url
        },
        template: `<div>The visited URL is: {{ url }}</div>`
      })
    
      renderer.renderToString(app, (err, html) => {
        if (err) {
          res.status(500).end('Internal Server Error')
          return
        }
        res.end(`
          <!DOCTYPE html>
          <html lang="en">
            <head><title>Hello</title></head>
            <body>${html}</body>
          </html>
        `)
      })
    })
    
    server.listen(8080)
    

    Rendering a Vue Instance

    // Step 1: Create a Vue instance
    const Vue = require('vue')
    const app = new Vue({
      template: `<div>Hello World</div>`
    })
    
    // Step 2: Create a renderer
    const renderer = require('vue-server-renderer').createRenderer()
    
    // Step 3: Render the Vue instance to HTML
    renderer.renderToString(app, (err, html) => {
      if (err) throw err
      console.log(html)
      // => <div data-server-rendered="true">Hello World</div>
    })
    
    // in 2.5.0+, returns a Promise if no callback is passed:
    renderer.renderToString(app).then(html => {
      console.log(html)
    }).catch(err => {
      console.error(err)
    })