使用NestJS发布NextJS

前言:NextJS是实现React SSR的框架,NestJS是NodeJS平台的MVC框架。 或者说:NextJS渲染React,NestJS则是实现MVC的WebServer。
相比较Koa而言,NestJS更好地实现了模块化(module)和路由,以及其他功能,如graphql、redis、mysql的集成、微服务等等。
本文将会说明如何使用NestJS承载NextJS,做到React的SSR

安装依赖项
npm i -g @nestjs/cli
cd [项目文件夹]

nest new my-app
npm install next react react-dom --save
code .
cd src
/* 建立相关文件*/
nest g module view
nest g controller view
nest g service view

更新.prettierrc

view.service.ts


import { Injectable, OnModuleInit } from '@nestjs/common';

import createServer from 'next';
import { NextServer } from 'next/dist/server/next';
import { Request, Response } from 'express';

@Injectable()
export class ViewService implements OnModuleInit {
  private server: NextServer;

  async onModuleInit(): Promise<void> {
    try {
      this.server = createServer({
        dev: true,
        dir: './src/client',
      });
      await this.server.prepare();
    } catch (error) {
      console.error(error);
    }
  }

  handler(req: Request, res: Response) {
    return this.server.getRequestHandler()(req, res);
  }
}

view.controller.ts


import { Controller, Get, Res, Req } from '@nestjs/common';
import { Request, Response } from 'express';
import { parse } from 'url';

import { ViewService } from './view.service';

@Controller('/')
export class ViewController {
  constructor(private viewService: ViewService) {}

  @Get('home')
  public async showHome(@Req() req: Request, @Res() res: Response) {
    await this.viewService.handler(req, res);
  }

  @Get('_next*')
  public async assets(@Req() req: Request, @Res() res: Response) {
    await this.viewService.handler(req, res);
  }

  @Get('favicon.ico')
  public async favicon(@Req() req: Request, @Res() res: Response) {
    await this.viewService.handler(req, res);
  }
}

view.module.ts


import { Module } from '@nestjs/common';

import { ViewController } from './view.controller';
import { ViewService } from './view.service';

@Module({
  imports: [],
  providers: [ViewService],
  controllers: [ViewController],
})
export class ViewModule {}

新建src/client/pages/home.tsx

import React from 'react';
import { NextPage } from 'next';

const Home: NextPage = () => {
  return <h1>Hello from NextJS! - Home</h1>;
};

export default Home;

启用jsx synthax语法, 在tsconfig.json文件中加入:

"jsx": "react",

为client项目添加配置
src->client

touch .eslintrc.js

module.exports = {
    parser: '@typescript-eslint/parser',
    parserOptions: {
      project: 'src/client/tsconfig.json',
      sourceType: 'module',
    },
    plugins: ['@typescript-eslint/eslint-plugin'],
    extends: [
      'plugin:@typescript-eslint/recommended',
      'prettier/@typescript-eslint',
      'plugin:prettier/recommended',
    ],
    root: true,
    env: {
      jest: true,
    },
    ignorePatterns: ['.eslintrc.js'],
    rules: {
      '@typescript-eslint/interface-name-prefix': 'off',
      '@typescript-eslint/explicit-function-return-type': 'off',
      '@typescript-eslint/explicit-module-boundary-types': 'off',
      '@typescript-eslint/no-explicit-any': 'off',
      '@typescript-eslint/no-unused-vars': ['warn', { 'argsIgnorePattern': '^_' }]
    },
  };
 

nest-cli.json

"sourceRoot": "src/server"

nest-cli 在该文件夹下定位 main.ts 文件作为入口,所以需要在src/server下添加main.js

import { NestFactory } from '@nestjs/core';
import { ViewModule } from './modules/view/view.module';

async function bootstrap() {
  const app = await NestFactory.create(ViewModule);
  await app.listen(3000);
}
bootstrap();

一切准备就绪后, npm run start

参考:https://github.com/kyle-mccarthy/nest-next
https://medium.com/geekculture/nestjs-react-next-js-in-one-mvc-repo-for-rapid-prototyping-faed42a194ca
https://github.com/thisismydesign/nestjs-starter

最后是源码链接

posted @ 2021-05-26 22:31  老胡Andy  阅读(2233)  评论(0编辑  收藏  举报