Nestjs + Vuejs routing

Viewed 86

I want to build monorepo with Vue and Nestjs. Main pages gonna be handled with Nestjs + Twig with paths /<page>. Admin panel gonna be at /admin/<page> (Vue app). And api routes, created with Nestjs /api/<route>. Vue admin builds in its dist directory and then we serve it via useStaticAssets method from https://github.com/fastify/fastify-static, here is Nestjs app's main.ts file:

import { NestFactory } from '@nestjs/core';
import {
  FastifyAdapter,
  NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { AppModule } from './app.module';
import helmet from '@fastify/helmet';
import { join } from 'path';

async function bootstrap() {
  const PORT = process.env.PORT || 3000;
  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter({ logger: true }),
  );

  await app.register(helmet);

  /** client assets and backend (uploaded files etc.) */
  app.useStaticAssets({
    root: join(__dirname, '..', 'public'),
    prefix: '/public/',
  });
  /** vue admin */
  app.useStaticAssets({
    root: join(__dirname, '..', 'vue-admin', 'dist'),
    prefix: '/admin',
    prefixAvoidTrailingSlash: true,
    decorateReply: false,
  });
  app.setViewEngine({
    engine: {
      twig: require('twig'),
    },
    templates: join(__dirname, '..', 'views'),
  });

  await app.listen(PORT);
}

bootstrap();

Expected behaviour: surfing Vue app pages without reloading and when refresh page in browser, get the same page. It works with Symfony, solution is here.

Actual behaviour: the same, but when refresh page at existing Vue route (e.g. /admin/about) it responds with 404. Seems like it tries to find static file, but we want it to be handled with Vue router.

I've tried to perform something like this to solve problem, but it doesn't work as expected:

import { All, Controller, Res } from '@nestjs/common';
import { FastifyReply } from 'fastify';
import { join } from 'path';
import { readFileSync } from 'fs';

@Controller()
export class AppController {
  @All('admin/*')
  vueAdmin(@Res() res: FastifyReply) {
    res
      .type('text/html')
      .send(
        readFileSync(
          join(__dirname, '..', 'vue-admin/dist/index.html'),
          'utf8',
        ),
      );
  }
}

0 Answers
Related