Skip to content

Commit

Permalink
docs for 3.1 (#491)
Browse files Browse the repository at this point in the history
* docs: add doc for 3.1

* add example for running as classic Node server
  • Loading branch information
conico974 authored Aug 22, 2024
1 parent 7886117 commit c91c83b
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 0 deletions.
37 changes: 37 additions & 0 deletions docs/pages/config/simple_example.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,43 @@ const config = {
export default config;
```

## Bundle for a classic Node server (With function splitting)

<Callout type="info" emoji="i">
This is not implemented in sst yet. You'll have to use your own IAC construct to deploy this.

Be aware that this uses the exact same system for ISR/SSG as the default lambda setup. So it will have to have all the proper permissions and env variable to interact with S3, DynamoDB and SQS (Or whatever you override it with). You can see [here](/inner_workings/components/server/node#special-overrides) for more details
</Callout>

```ts
import type { OpenNextConfig } from 'open-next/types/open-next';
const config = {
// In this case, the default server is meant to run as a classic Node server
// To execute the server you need to run `node index.mjs` inside `.open-next/server-functions/default`
default: {
override: {
wrapper: 'node',
converter: 'node',
// This is necessary to generate a simple dockerfile and for the generated output to know that it needs to deploy on docker
// You can also provide a string here (i.e. the content of your Dockerfile) which will be used to create the dockerfile
// You don't have to provide this if you plan on not using docker, or if you plan on using your own custom dockerfile
generateDockerfile: true,
},
},
// You can define multiple functions here, each with its own routes, patterns and overrides
functions: {
// In this case both the api route is in lambda and the rest is in node
myFn: {
// Patterns needs to use the glob pattern
patterns: ['api/*'],
routes: ['app/api/test/route', 'app/api/test2/route'],
},
},
} satisfies OpenNextConfig;

export default config;
```

## Edge runtime splitted function

This will generate 2 server functions, the default one and the edge one. The edge one will still be deployed as a lambda function, but it will be deployed in the edge runtime.
Expand Down
2 changes: 2 additions & 0 deletions docs/pages/inner_workings/_meta.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{
"routing": "Routing Layer",
"caching": "Caching (ISR/SSG)",
"cache_interception": "Optional Cache Interception",
"components": "Main Components",
"architecture": "Default Architecture"
}
32 changes: 32 additions & 0 deletions docs/pages/inner_workings/cache_interception.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
By default OpenNext override the cache system of Next.js to store the cache in S3(Or any other incremental cache provider defined in config) using [`cacheHandler` from `next.config.js`](https://nextjs.org/docs/app/api-reference/next-config-js/incrementalCacheHandlerPath). It also uses a queue system to handle ISR revalidation.

This is great but it still has go through `NextServer` which by default will load the js associated with the page even if the page is cached. This is not ideal for cold start, and makes it impossible to serve ISR/SSG pages inside an external middleware.

Since OpenNext 3.1, we have added a new feature that we call Cache Interception that allows you to intercept the cache system directly inside OpenNext routing layer and serve the page directly from the cache without going through `NextServer`. If the cache interception fail, the request will be forwarded to the `NextServer` as usual.

Enabling this alongside external middleware means that the external middleware will need to have all the proper permissions and env variable to interact with S3, DynamoDB and SQS (Or whatever you override it with). You can see [here](/inner_workings/components/server/node#special-overrides) for more details.

This has the following benefits:
- Faster cold start (No need to load the js associated with the page if the page is cached)
- ISR/SSG route can be served directly from an external middleware
- If the external middleware is in front of the CDN, the middleware can be used for every route including ISR/SSG
- This will allow PPR (Partial Prerendering) to work as intended and demonstrated by Vercel.¹ **This is not implemented yet**.

To enable cache interception, you need to add `enableCacheInterception` option in the `open-next.config.ts` file.

```ts
// open-next.config.ts
import type { OpenNextConfig } from 'open-next/types/open-next';
const config = {
default: {
},
dangerous: {
enableCacheInterception: true,
},
} satisfies OpenNextConfig;

export default config;

```

1. PPR outside of vercel does not work in the way they demonstrated. The reason is that the cache system is handled by `NextServer` and it has to reach the server **every single time**. PPR pages cannot be served from the CDN when using `next start` or the standalone ouput as of now. In some cases PPR without vercel can be slower than SSR (especially if your cache is not using the default filesystem).
22 changes: 22 additions & 0 deletions docs/pages/inner_workings/routing.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
OpenNext doesn't use the default routing provided by Next.js. Instead, it uses its own routing system.

Historically, OpenNext used the same routing system as Next.js. But in Next 13.4.13, they moved the routing system outside of `NextServer` and separated every major part of the app (i.e. app router, page router and the routing) inside jest workers. This caused terrible cold start (around 8s for a default `create next-app` app) and made it impossible to serve ISR/SSG pages inside lambda. Since then, OpenNext has been using its own routing system for every app that uses Next 13.4.13 or higher. FYI Vercel use an undocumented `minimalMode` inside `NextServer` to bypass the routing and cache system so that it is done in their infra instead of the lambda.

This move also allow OpenNext to have a more flexible routing system. With OpenNext you can put the routing layer in a function (lambda@edge or cloudflare workers) in front of your server. You can even serve ISR/SSG directly from the routing layer.

Here is a list of features that OpenNext routing system handle:

- From `next.config.js` (the rest is handled by `NextServer` itself):
- Headers
- Redirects
- Rewrites
- basePath
- i18n
- [Middleware](#next-middleware)
- [Optional Cache Interception](/inner_workings/cache_interception) (i.e. serve ISR/SSG directly from the routing layer)
- Handle 404 in some cases (i.e. when the page does not correspond to any of the regex routes)


#### Next Middleware

The Next middleware in OpenNext is not running in the same way as in Next.js. In Next.js, the middleware is running inside the `NextServer` inside a fake edge runtime. In OpenNext, we modify the middleware and run it fully inside the routing layer. So if you run the routing layer in Node, you can use Node api inside the middleware (it's a bit tricky because it won't work with `next dev` and involves some workaround because Next will remove Node api during bundling. Some example [here](/config/custom_overrides#define-a-global-to-use-node-in-the-middleware)).

0 comments on commit c91c83b

Please sign in to comment.