npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@stnekroman/nest-next-router

v0.0.6

Published

Bridge between Nest to Next, top-level request router

Downloads

170

Readme

Stand With Ukraine

Nest-Nest Router

Inspided by https://github.com/kyle-mccarthy/nest-next, but done right.
Bridge between Nest backend and Next back&frontend - on the same host.
Allows to use all Next features (like SSR) while keeping running Nest backend.
Main host is Nest (over express/Fastify), which runs inside Next custom server.

Main idea of routing request between two systems - top-level request switcher/router.

Installation

npm

npm i @stnekroman/nest-next-router

yarn

yarn add @stnekroman/nest-next-router

Basic usage with express.js

import {
  NestNextRouterModule,
  RequestRouteHandleType,
} from '@stnekroman/nest-next-router';

@Module({
  imports: [
    NestNextRouterModule.forRootAsync(
      Next({
        // your own Next config here
      }),
      {
        routeRequest: async (request: express.Request, response: express.Response): Promise<RequestRouteHandleType> => {
          if (request.url.startsWith('/rest')) {
            return RequestRouteHandleType.NEST; // forward all /api requests to Nest backend
          } else {
            return RequestRouteHandleType.NEXT; // all other requests will go to Next
          }
        }
      }
    )
  ]
})
export class RootModule {}

Basic usage with Fastify

import {
  NestNextRouterModule,
  RequestRouteHandleType,
} from '@stnekroman/nest-next-router';

@Module({
  imports: [
    NestNextRouterModule.forRootAsync(
      Next({
        // your own Next config here
      }),
      {
        serverType: HttpServerType.FASTIFY,
        routeRequest: async (request: FastifyRequest, response: FastifyReply): Promise<RequestRouteHandleType> => {
          if (request.url.startsWith('/rest')) {
            return RequestRouteHandleType.NEST; // forward all /api requests to Nest backend
          } else {
            return RequestRouteHandleType.NEXT; // all other requests will go to Next
          }
        }
      }
    )
  ]
})
export class RootModule {}

Why?

Why not "nest-next", after all?
Because this solutions just routes incomming requests. So it's pretty easy and clear - you just define, which requests and where are served.
Depending on URL, header params, weather out of the window - it's up to you.
Thus this makes usage of top-level routing very versatile.

And! Nest-next provides Next render engine to Nest, and allows only that.
So routing of pages is done on Nest side. Thus, if someday you will decide to split Nest/Next to separate microservices (in order to scale horizontally) - you will need to fallback to Next routing anaway. So more refactoring.
While Next file-based routing with App Router (introduced in Next 13) is more versatile (especially for SEO) than Nest, so whay wire yourself to Nest view/render routing?

And! Even more, Nest-next provides render engine, but only oine bridge between Nest->Next remains - it's ability to route 404 errors from Nest to Next, nothing more.
That means, that you loose ability (in out-of-the box configuration) to serve on Next things like: favicon.ico, Next metadata (robots.txt), static files (CSS bundles, images from Next directories)
Technically, you can write your custom route rules to EACH route (favicon.ico) in order to forward to Next (actually - render content via Next). But hopefully you understand how that is uncool.

I want Next render engine in Nest. Now!

First of all, you don't need that - just use Next file-based routing and that's all.
But in case if you really need Next render engine on Nest side and insist, you can do it (while not recommended):

import {
  NestNextRouterModule,
  NextRenderModule,
  RequestRouteHandleType,
} from '@stnekroman/nest-next-router';

@Module({
  imports: [
    NestNextRouterModule.forRootAsync(
      Next({
        // config
      }),
      {
        routeRequest: async (request: express.Request, response: express.Response): Promise<RequestRouteHandleType> => {
          if (request.url.startsWith('/rest')) {
            return RequestRouteHandleType.NEST; // forward all /api requests to Nest backend
          } else {
            return RequestRouteHandleType.NEXT; // all other requests will go to Next
          }
        }
      }
    ),
    NextRenderModule.forRoot() // just add this
  ]
})
export class RootModule {}

Ability to pass 404 http error down to Next

User case: to render nice-looking not_found Next page instead of standard Nest json response.
As nest-next had ability to pass 404 errors down to Next (while incorrectly), here you can do the same.
Just apply global filter:

@Module({
  imports: [
    // ...
  ],
  providers: [
    {
      provide: APP_FILTER,
      useClass: Http404ExceptionFilter,
    },
  ]
})
export class RootModule {}

That's it. You can apply that filter globalle, per controller or per route basis.
Looking on how filter is done you can craft your own and apply where you need.

Best practices around routing

Avoid use of

app.setGlobalPrefix('rest');

Because in this case Nest will just reject any request not in scope of /rest.
So it will be impossible to forward such requests to Next.
Better to use config like:

app.setGlobalPrefix('rest', {
  exclude: ['/'],
});

In this case Nest will continue to serve requests at root, and will continue to call middleware for them. Or, if that is not suitable for you for some magic reason, you have two other options:

Option I
Manually declare fully-qualified path on each RestController via @Controller decorator.
Option II
According to https://docs.nestjs.com/recipes/router-module

@Module({
  imports: [
    // ...

    ItemsModule,

    RouterModule.register([
      {
        path: '/rest',
        children: [
          {
            path: '/items',
            module: ItemsModule,
          },
        ],
      },
    ]),
  ]
})
export class RootModule {}

API

NestNextRouterModuleOptions

Options, passed to NestNextRouterModule.forRootAsync(...) method.

| Param | Description | | -------------- | ----------------------------------------------------------------------------------------------- | | serverType | Type of underlaying HTTP server, if not specified - express by default | | routeRequest | method to handle incomming requests to say to which direction to route them. | | | Possible return values: | | | * NEST - forward request to Nest | | | *NEXT - forward request to Next | | | *CUSTOM - you way have already handled the request differently - nothing to do from our side |

NextRenderModuleOptions

Options passed to NextRenderModule

| Param | Description | | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | viewsDir | Prefix, which to prepend to view, which required to resolve. | | | For example, you may use @Render('that'), but in reality your page that sits on path subdir/thaton Next side. So viewsDir: subdir/ should help |


License MIT, good luck