Skip to content

ananiy/nest-next-module

 
 

Repository files navigation

nest-next-module

简介

nestjs中使用nextjs做模板渲染引擎.

由于需求要做SEO, 自然而然的想到了SSR. 在对比Angular Universal, nuxtjs, nextjs之后, 选择了nextjs.

同时发现, nextjs如果要增加动态路由等功能, 需要后台去做支持, 于是选择了typescript支持最完善的nestjs框架.

于是如何将nestjsnextjs一起使用, 就成了我们主要解决的问题.

nestjsnextjs中都包含一个node http的实现, 因此需要将nestjs的页面路由请求, 转发给nextjs去处理渲染模板, 以及一些静态资源的访问也需要做转发.

nestjsissues 1122Kyle McCarthy写了一个nest-next包, 仔细阅读了其源码之后, 我决定自己写一个绑定模块.

原因主要是因为nest-next篡改了nestjsexpress中的模板引擎, 侵入性比较强, 如果我还需要用express的模板渲染的话, 是不可能做到的. 其次nest-next的模块导入方式不符合nestjs模块正常使用方式, 需要手动启动next-server并绑定.

Demo

nest-next-module-demo

nest-next-module-demo-with-typescript

开始使用

  • 安装@nestjs/cli, 新建一个项目:
$ npm i -g @nestjs/cli
$ nest new nest-next-demo # 请选择使用yarn安装模块
  • 安装NestNextModule包, 和nextjs相关依赖:
$ yarn add nest-next-module next react react-dom
  • AppModule中导入NestNextModule:
// src/app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { NestNextModule } from 'nest-next-module';

const dev = process.env.NODE_ENV !== 'production';

@Module({
  imports: [NestNextModule.forRoot({ dev })],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
  • AppController中创建路由, 使用nextjsrender渲染模板:
// src/app.controller.ts

import { Controller, Get, Res } from '@nestjs/common';
import { NextResponse } from 'nest-next-module';

@Controller()
export class AppController {
  @Get()
  index(@Res() res: NextResponse) {
    return res.nextRender('/index');
  }
}
  • 根目录新建pages文件夹, 新建index.jsx文件:
// pages/index.tsx

import React from 'react';

const Page = () => {
  return <h1>hello nest next!</h1>;
};

export default Page;
  • 启动项目:
$ yarn start
  • 打开浏览器, 访问http://localhost:3000/.

在nextjs中使用typescript

  • 为了在nextjs中使用typescript, 需要安装@zeit/next-typescript包, 和一些的声明文件包:
$ yarn add @zeit/next-typescript
$ yarn add @types/next @types/react @types/react-dom -D
  • 项目根目录新建.babelrc.jsnext.config.js:
// .babelrc.js
module.exports = {
  presets: ['next/babel', '@zeit/next-typescript/babel'],
};

// next.config.js
const withTypescript = require('@zeit/next-typescript');

module.exports = withTypescript({
  useFileSystemPublicRoutes: false,
});
  • 更新下tsconfig.json, 增加了jsx, moduleResolution, esModuleInterop的编译选项配置:
{
  "compilerOptions": {
    "jsx": "preserve",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es6",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true
  },
  "exclude": ["node_modules"]
}
  • 重命名pages/index.jsxpages/index.tsx, 加入类型:
import React from 'react';
import { NextFC } from 'next';

const Page: NextFC = () => {
  return <h1>hello nest next!</h1>;
};

export default Page;
  • 启动项目:
$ yarn start
  • 打开浏览器, 访问http://localhost:3000/.

About

using nestjs and nextjs together!

Resources

License

Stars

Watchers

Forks

Packages

No packages published