Nestjs + Vuejs 路由

问题描述 投票:0回答:1

我想用 Vue 和 Nestjs 构建 monorepo。主要页面将使用 Nestjs + Twig 和路径

/<page>
进行处理。管理面板位于
/admin/<page>
(Vue 应用程序)。以及使用 Nestjs
/api/<route>
创建的 api 路由。 Vue admin 在其
dist
目录中构建,然后我们通过 https://github.com/fastify/fastify-static 中的 useStaticAssets 方法提供它,这是 Nestjs 应用程序的 main.ts 文件:

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();

预期行为:无需重新加载即可浏览 Vue 应用程序页面,并且在浏览器中刷新页面时,获得相同的页面。它可以与 Symfony 配合使用,解决方案是here

实际行为:相同,但是当在现有 Vue 路由(例如 /admin/about)刷新页面时,它会响应 404。看起来它试图查找静态文件,但我们希望它由 Vue 路由器处理。

我尝试执行类似的操作来解决问题,但它没有按预期工作:

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',
        ),
      );
  }
}

vue.js nestjs vue-router fastify
1个回答
0
投票

我在这个问题中想要实现的行为已经实现,并且按预期工作。 main.ts 的最终代码:

import { NestFactory } from '@nestjs/core';
import {
  FastifyAdapter,
  NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { AppModule } from './app.module';
import fastifyHelmet from '@fastify/helmet';
import fastyfyMultipart from '@fastify/multipart';
import { join } from 'path';
import { queryStringParse } from './utils';
import { readFileSync } from 'node:fs';
import * as fastifyHttpsRedirect from 'fastify-https-redirect';

async function bootstrap() {
  const HOST = process.env.HOST || '127.0.0.1';
  const PORT = process.env.USE_HTTPS ? 443 : process.env.PORT || 3000;

  const fastifyAdapterOptions: any = {
    logger: true,
    http2: true,
    querystringParser: (str) => queryStringParse(str),
  };

  if (process.env.USE_HTTPS) {
    const httpsOptions = {
      key: readFileSync(join(__dirname, '..', 'certs', 'ssl.key')),
      cert: readFileSync(join(__dirname, '..', 'certs', 'ssl.crt')),
      allowHTTP1: true,
      requestCert: false, // process.env.NODE_ENV === 'production',
      rejectUnauthorized: false, // process.env.NODE_ENV === 'production',
    };
    fastifyAdapterOptions.https = httpsOptions;
  }

  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter(fastifyAdapterOptions),
  );

  app.register(fastifyHttpsRedirect);
  app.register(fastyfyMultipart);

  if (process.env.NODE_ENV === 'development') {
    app.enableCors({
      credentials: true,
      origin: true,
    });
  }

  await app.register(fastifyHelmet, {
    crossOriginResourcePolicy: false,
    contentSecurityPolicy: {
      directives: {
        'img-src': ["'self'", 'https: data: blob:'],
      },
    },
  });

  /** 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: {
      nunjucks: require('nunjucks'),
    },
    options: {
      onConfigure: (env) => {
        // eslint-disable-next-line @typescript-eslint/no-var-requires
        env.addFilter('date', require('nunjucks-date-filter'));
      },
      autoescape: true,
      web: {
        useCache: process.env.NODE_ENV === 'production',
        async: process.env.NODE_ENV === 'production',
      },
      debug: process.env.NODE_ENV === 'development',
      watch: process.env.NODE_ENV === 'development',
    },
    templates: join(__dirname, '..', 'views'),
  });

  await app.listen(PORT, HOST);
}

bootstrap();

但是这种技术解决方案也有一些缺点。 Fastify 团队在此解释:https://fastify.dev/docs/latest/Guides/Recommendations/#use-a-reverse-proxy

© www.soinside.com 2019 - 2024. All rights reserved.