diff --git a/pages/aws/config/custom_overrides.mdx b/pages/aws/config/custom_overrides.mdx index 7e319a9..c4c8c1d 100644 --- a/pages/aws/config/custom_overrides.mdx +++ b/pages/aws/config/custom_overrides.mdx @@ -3,7 +3,7 @@ import { Callout } from 'nextra/components' In some cases the simple example is not enough, and you want to add more customization to your server. This is where the lazy loaded overrides come in. You can override any part of the server by providing a function that returns a promise that resolves to the override object. This is useful when you want to add custom logic to your server, like adding a custom queue, or adding a custom converter. -Be careful if you use the edge runtime (either in a function or by using the external middleware), we do 2 compilations of the `open-next.config.ts`, one for node and one for the edge runtime. If you're using some custom overrides, you likely want to add +Be careful if you use the edge runtime (either in a function or by using the external middleware), we do 2 compilations of the `open-next.config.ts`, one for node and one for the edge runtime. If you're using some custom overrides, you likely want to add ```ts edgeExternals: ['./customWrapper', './anyOtherOverrideUsed'] ``` @@ -13,14 +13,14 @@ to your `open-next.config.ts` to avoid the edge runtime to try to compile overri ## Custom converter -Sometimes you might want to modify the object received by OpenNext. For example `Config.YOUR_SECRET_KEY` from sst cannot be used in the middleware, so you might want to add it to the headers. This is where the custom converter comes in. You can add a custom converter to modify the object before it is passed to OpenNext. +Sometimes you might want to modify the object received by OpenNext. For example `Config.YOUR_SECRET_KEY` from sst cannot be used in the middleware, so you might want to add it to the headers. This is where the custom converter comes in. You can add a custom converter to modify the object before it is passed to OpenNext. You'll still have to use a fallback value during dev as this is not used by the dev server. ```ts // customConverter.ts -import converter from 'open-next/converters/aws-apigw-v2.js' -import type { Converter } from 'open-next/types/open-next' +import converter from '@opennextjs/aws/overrides/converters/aws-apigw-v2.js' +import type { Converter } from '@opennextjs/aws/types/overrides' import { Config } from 'sst/node/Config' const mySecretKey = Config.YOUR_SECRET_KEY @@ -28,7 +28,7 @@ export default { convertFrom: async (event) => { const result = await converter.convertFrom(event) return { - ...result, + ...result, headers: { ...result.headers, 'inserted-in-converter': '1', @@ -52,7 +52,7 @@ export default { ```ts // open-next.config.ts -import type { OpenNextConfig } from 'open-next/types/open-next' +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next' const config = { default: { @@ -70,7 +70,7 @@ Here we provide a few examples for some custom wrapper. ```ts // customWrapper.ts -import defaultWrapper from 'open-next/wrappers/aws-lambda.js' +import defaultWrapper from '@opennextjs/aws/overrides/wrappers/aws-lambda.js' //Here you can define some globals declare global { @@ -88,7 +88,7 @@ export default defaultWrapper ```ts // open-next.config.ts -import type { OpenNextConfig } from 'open-next/types/open-next' +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next' const config = { default: { override: { @@ -106,8 +106,8 @@ import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' // Here you need to mock the global if not present -// One way to avoid issues with different implementation would be to create an api endpoint -// that uses the exact same logic as the global you defined earlier, +// One way to avoid issues with different implementation would be to create an api endpoint +// that uses the exact same logic as the global you defined earlier, // and that is only available during development i.e. /api/dev/myApi if(!globalThis.myApi) { globalThis.myApi = async () => { @@ -117,7 +117,7 @@ if(!globalThis.myApi) { export function middleware(request: NextRequest) { // You can also send an error in the api endpoint itself - // Or you could add all the dev endpoint in their own lambda + // Or you could add all the dev endpoint in their own lambda // that you do not deploy in production if(request.nextUrl.pathname.startsWith('/api/dev') && process.env.NODE_ENV === 'production') { return NextResponse('This route is only available in development',{ @@ -129,7 +129,7 @@ export function middleware(request: NextRequest) { // ... your code here } - + ``` @@ -137,8 +137,8 @@ export function middleware(request: NextRequest) { ```ts // customWrapper.ts -import streamingWrapper from 'open-next/wrappers/aws-lambda.js' -import {WrapperHandler} from 'open-next/types/open-next' +import streamingWrapper from '@opennextjs/aws/overrides/wrappers/aws-lambda.js' +import type { WrapperHandler } from '@opennextjs/aws/types/overrides' import middy from '@middy/core' import httpSecurityHeaders from '@middy/http-security-headers' @@ -158,7 +158,7 @@ export default { ```ts // open-next.config.ts -import type { OpenNextConfig } from 'open-next/types/open-next' +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next' const config = { default: { override: { @@ -182,11 +182,11 @@ import type { APIGatewayProxyEventV2, APIGatewayProxyResultV2, } from "aws-lambda"; -import type { StreamCreator } from "open-next/http/openNextResponse"; +import type { StreamCreator } from "@opennextjs/aws/http/openNextResponse"; import { Writable } from "node:stream"; -import { WarmerEvent, WarmerResponse } from "open-next/adapters/warmer-function"; -import type { WrapperHandler } from "open-next/types/open-next"; +import { WarmerEvent, WarmerResponse } from "@opennextjs/aws/adapters/warmer-function"; +import type { WrapperHandler } from "@opennextjs/aws/types/overrides"; type AwsLambdaEvent = | APIGatewayProxyEventV2 @@ -268,7 +268,7 @@ export default { ```ts // open-next.config.ts -import type { OpenNextConfig } from 'open-next/types/open-next' +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next' const config = { default: { override: { diff --git a/pages/aws/config/full_example.mdx b/pages/aws/config/full_example.mdx index e0ace38..0545c9e 100644 --- a/pages/aws/config/full_example.mdx +++ b/pages/aws/config/full_example.mdx @@ -1,4 +1,4 @@ -Here is a detailed example of an `open-next.config.ts` file: +Here is a detailed example of an `open-next.config.ts` file: This file need to be at the same place as your `next.config.js` file `server` in here could refer to a lambda function, a docker container, a node server or whatever that can support running nodejs code. (Even cloudflare workers in the future) @@ -6,12 +6,12 @@ This file need to be at the same place as your `next.config.js` file For more information about the options here, take a look at the [components section](/aws/components/overview). ```ts -import type { OpenNextConfig } from 'open-next/types/open-next' +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next' const config = { default: { // This is the default server, similar to the server-function in open-next v2 - // You don't have to provide the below, by default it will generate an output + // You don't have to provide the below, by default it will generate an output // for normal lambda as in open-next v2 - override: { + override: { wrapper: "aws-lambda-streaming", // This is necessary to enable lambda streaming // You can override any part that is a `LazyLoadedOverride` this way queue: () => Promise.resolve({ @@ -24,7 +24,7 @@ const config = { }, // Below we define the functions that we want to deploy in a different server // This is only used if you want to split the server into multiple servers - functions: { + functions: { ssr: { routes: [ "app/api/isr/route", "app/api/sse/route", "app/api/revalidateTag/route", // app dir Api routes @@ -37,7 +37,7 @@ const config = { }, // This enables the bundled next server which is faster and reduce the size of the server // This is also experimental and might not work in all cases - experimentalBundledNextServer: true + experimentalBundledNextServer: true }, pageSsr: { routes: ["pages/pageSsr"], // For page dir routes should be in the form `pages/${route}` without the extension, it should match the filesystem @@ -56,24 +56,24 @@ const config = { routes: ["app/ssr/page"], patterns: ["ssr"], override: {} - } + } }, - // By setting this, it will create another bundle for the middleware, - // and the middleware will be deployed in a separate server. + // By setting this, it will create another bundle for the middleware, + // and the middleware will be deployed in a separate server. // If not set middleware will be bundled inside the servers // It could be in lambda@edge, cloudflare workers, or anywhere else // By default it uses lambda@edge // This is not implemented in the reference construct implementation. // This is optional, but might be necessary if you split your app into multiple servers middleware: { - external: true + external: true } // Optional imageOptimization: { // This is the architecture of the image, it could be x64 or arm64 // This is necessary to bundle the proper version of sharp - arch: "x64", + arch: "x64", } // If you want to override the default build command, you can do it here @@ -83,14 +83,14 @@ const config = { dangerous: { // This will disable the tag cache // You can use it safely on page router, on app router it will break revalidateTag and revalidatePath - disableTagCache: true, + disableTagCache: true, // This will disable the incremental cache // This is generally not recommended, as this is necessary for ISR AND SSG routes as well as the fetch cache - disableIncrementalCache: true, + disableIncrementalCache: true, } //The path to the target folder of build output from the `buildCommand` option (the path which will contain the `.next` and `.open-next` folders). This path is relative from the current process.cwd() - Optional default to "." - buildOutputPath: "build", + buildOutputPath: "build", //The path to the root of the Next.js app's source code. This path is relative from the current process.cwd(). - Optional default to "." appPath: "app", diff --git a/pages/aws/config/nx.mdx b/pages/aws/config/nx.mdx index a0d034a..6e7c2b4 100644 --- a/pages/aws/config/nx.mdx +++ b/pages/aws/config/nx.mdx @@ -3,14 +3,14 @@ Here's a detailed exampled of how to add open-next + SST to an existing Nx works 1. install `open-next`: `pnpm add —save-dev open-next` -2. Update your `apps/next-site/next.config.js` add `output: ‘standalone’`, and you want to add `experimental.outputFileTracingRoot`, it should look a little like this: +2. Update your `apps/next-site/next.config.js` add `output: ‘standalone’`, and you want to add `experimental.outputFileTracingRoot`, it should look a little like this: ```javascript //@ts-check - + // eslint-disable-next-line @typescript-eslint/no-var-requires const { composePlugins, withNx } = require('@nx/next'); const { join } = require('node:path'); - + /** * @type {import('@nx/next/plugins/with-nx').WithNxOptions} **/ @@ -26,18 +26,18 @@ const nextConfig = { + outputFileTracingRoot: join(__dirname, '../../'), + }, }; - + const plugins = [ // Add more Next.js plugins to this list if needed. withNx, ]; - + module.exports = composePlugins(...plugins)(nextConfig); ``` -3. Create `open-next.config.js` inside your apps root directory, it should look a little something like this: +3. Create `open-next.config.js` inside your apps root directory, it should look a little something like this: ```javascript -import type { OpenNextConfig } from 'open-next/types/open-next'; +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next'; const config = { default: {}, @@ -50,13 +50,13 @@ const config = { export default config; ``` -4. Set up nx's targets/tasks +4. Set up nx's targets/tasks Now we have open-next configuration set up, you can try to run `open-next build` and depending on whether you have already built your next app or not -it might even work. +it might even work. However, we don't want to rely on needing to manually running a build every time we want to deploy a change, so instead we can set up a target. -We do this in your project's `project.json` (in this case, living at `apps/next-site/project`), we want to find the targets object and update it: +We do this in your project's `project.json` (in this case, living at `apps/next-site/project`), we want to find the targets object and update it: ```diff { "name": "next-site", @@ -66,7 +66,7 @@ We do this in your project's `project.json` (in this case, living at `apps/next- "tags": [], "targets": { + "open-next-build": { // name of the target, this is what you will call -+ "executor": "nx:run-commands", ++ "executor": "nx:run-commands", + "dependsOn": ["build"], // this ensures that Nx will build our next app before running this command. + "cache": true, // cache the output, good for if you want to use DTE/Nx cloud + "outputs": ["{projectRoot}/.open-next"], // tell nx where the output lives @@ -79,7 +79,7 @@ We do this in your project's `project.json` (in this case, living at `apps/next- } ``` -Next we need to add the open-next directory to our eslint's `ignorePatterns` array +Next we need to add the open-next directory to our eslint's `ignorePatterns` array ```diff { "extends": [ @@ -120,13 +120,13 @@ now, when you run `nx open-next-build next-site`, nx will automatically build th 5. Deploying with SST -Now, we have a built app, ready to deploy, so how do we get it onto SST/AWS ? Good question! +Now, we have a built app, ready to deploy, so how do we get it onto SST/AWS ? Good question! We are using `sst ion` in this example. i will assume you have already have the cli installed, (if not, check here on how!)[https://ion.sst.dev/], but we will not use the SST cli to init this project, because it wants to add a package.json to your next app, and it will look like it's working, but you will end up with a big far server error (all because the package.json overrides whatever nx _thinks_ there should be, and it will miss a bunch of dependencies). we will instead manually set this up: - let's add the sst package with `pnpm add sst@ion`, and the required packages for SST to work with AWS `pnpm add --save-dev aws-cdk-lib constructs @types/aws-lambda` -- then we want to manually create an `sst.config.ts` file in `apps/next-site` that looks like this: +- then we want to manually create an `sst.config.ts` file in `apps/next-site` that looks like this: ```typescript /// @@ -150,7 +150,7 @@ export default $config({ - now, you probably see some type errors, as SST is not initialized yet, but we can resolve this by running ```bash -$ cd apps/next-site && sst install +$ cd apps/next-site && sst install ``` this will resolve the type issues and initialise SST. @@ -197,7 +197,7 @@ this will resolve the type issues and initialise SST. } ``` -- now, if you want to run `sst dev` you can do so with `sst dev "nx dev next-site"` similarly deploying can be done with `sst deploy`...but you probably want to set up that task chaining, again we can do that by adding a target to your app, and setting it's `dependsOn` to the `open-next-build`, here's what it might look like: +- now, if you want to run `sst dev` you can do so with `sst dev "nx dev next-site"` similarly deploying can be done with `sst deploy`...but you probably want to set up that task chaining, again we can do that by adding a target to your app, and setting it's `dependsOn` to the `open-next-build`, here's what it might look like: ```diff { @@ -208,9 +208,9 @@ this will resolve the type issues and initialise SST. "tags": [], "targets": { "open-next-build": { - "executor": "nx:run-commands", + "executor": "nx:run-commands", "dependsOn": ["build"], - "cache": true, + "cache": true, "outputs": ["{projectRoot}/.open-next"], "options": { "cwd": "apps/next-site", @@ -234,7 +234,7 @@ this will resolve the type issues and initialise SST. + "args": ["--stage=staging"] + }, + "dev": { -+ "args": ["--stage=development"] ++ "args": ["--stage=development"] + } + } + } @@ -244,9 +244,9 @@ this will resolve the type issues and initialise SST. ``` -now we can run (or if you want a custom stage, you can simply do `nx deploy next-site --stage this-is-my-stage` and it will be passed directly to the sst command). +now we can run (or if you want a custom stage, you can simply do `nx deploy next-site --stage this-is-my-stage` and it will be passed directly to the sst command). ```bash $ nx deploy next-site --configuration dev # using dev configuration (which sets the stage to development) # nx deploy next-site -c dev # OR -# nx deploy next-site --stage my-stage # Custom Stage +# nx deploy next-site --stage my-stage # Custom Stage ``` \ No newline at end of file diff --git a/pages/aws/config/simple_example.mdx b/pages/aws/config/simple_example.mdx index 5fde1fe..a401dec 100644 --- a/pages/aws/config/simple_example.mdx +++ b/pages/aws/config/simple_example.mdx @@ -22,7 +22,7 @@ Here you can find the most common `open-next.config.ts` file examples that you c ```ts -import type { OpenNextConfig } from 'open-next/types/open-next'; +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next'; const config = { default: { override: { @@ -37,7 +37,7 @@ export default config; ## Splitting the server ```ts -import type { OpenNextConfig } from 'open-next/types/open-next'; +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next'; const config = { // This is the default server, similar to the server-function in open-next v2 // In this case we are not providing any override, so it will generate a normal lambda (i.e. no streaming) @@ -72,7 +72,7 @@ export default config; ```ts -import type { OpenNextConfig } from 'open-next/types/open-next'; +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next'; const config = { default: { override: { @@ -89,7 +89,7 @@ export default config; ## Running in Lambda@Edge ```ts -import type { OpenNextConfig } from 'open-next/types/open-next'; +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next'; const config = { default: { placement: 'global', @@ -111,7 +111,7 @@ Be aware that this uses the exact same system for ISR/SSG as the default lambda ```ts -import type { OpenNextConfig } from 'open-next/types/open-next'; +import type { OpenNextConfig } from '@opennextjs/aws/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` @@ -146,7 +146,7 @@ This will generate 2 server functions, the default one and the edge one. The edg Edge runtime function have less cold start time, but you can only deploy one route per function. They also do not have the middleware bundled in the function, so you need to use external middleware if you need it in front of the edge function. ```ts -import type { OpenNextConfig } from 'open-next/types/open-next'; +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next'; const config = { default: {}, functions: { @@ -169,7 +169,7 @@ With the default middleware configuration, it is bundled for a deployment in lam This is how you can do it: ```ts -import type { OpenNextConfig } from 'open-next/types/open-next'; +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next'; const config = { default: {}, functions: { diff --git a/pages/aws/contribute.mdx b/pages/aws/contribute.mdx index 7c78267..eb47b23 100644 --- a/pages/aws/contribute.mdx +++ b/pages/aws/contribute.mdx @@ -3,7 +3,7 @@ To run `OpenNext` locally: 1. Clone [this repository](https://github.com/opennextjs/opennextjs-aws). 2. Build `open-next`: ```bash - cd open-next + cd opennextjs-aws pnpm build ``` 3. Run `open-next` in watch mode: @@ -13,7 +13,7 @@ To run `OpenNext` locally: 4. Now, you can make changes in `open-next` and build your Next.js app to test the changes. ```bash cd path/to/my/nextjs/app - path/to/open-next/packages/open-next/dist/index.js build + path/to/opennextjs-aws/packages/open-next/dist/index.js build ``` It can be a bit cumbersome to need to deploy every time you want to test changes. If your change is not dependent on the wrapper or the converter, then you can create a custom `open-next.config.ts` file, you can take a look [here](/aws/contribute/local_run) for more information. diff --git a/pages/aws/contribute/local_run.mdx b/pages/aws/contribute/local_run.mdx index 4a46179..9eeebf4 100644 --- a/pages/aws/contribute/local_run.mdx +++ b/pages/aws/contribute/local_run.mdx @@ -3,16 +3,16 @@ When making some changes to OpenNext, it can be a bit cumbersome to need to depl To run `OpenNext` locally: ```bash # This is to build (the config-path is needed if you use a different name than the default one) -node /path/to/open-next/packages/open-next/dist/index.js build --config-path open-next.local.config.ts +node /path/to/opennextjs-aws/packages/open-next/dist/index.js build --config-path open-next.local.config.ts # Then to run the server node .open-next/server-functions/default/index.mjs ``` ```typescript -// open-next.local.config.ts - -// A good practice would be to use a different name so that it doesn't conflict +// open-next.local.config.ts - +// A good practice would be to use a different name so that it doesn't conflict // with your existing open-next.config.ts i.e. open-next.local.config.ts -import type {OpenNextConfig} from 'open-next/types/open-next' +import type {OpenNextConfig} from '@opennextjs/aws/types/open-next' const config = { default: { @@ -60,13 +60,13 @@ export default config // dev/wrapper.ts // You'll need to install express import express from 'express' -// The proxy is used to proxy the image optimization server +// The proxy is used to proxy the image optimization server // you don't have to use it, but image request will return 500 error import proxy from 'express-http-proxy' import { fork } from 'child_process' -import type { StreamCreator } from "open-next/http/openNextResponse"; -import type { WrapperHandler } from "open-next/types/open-next"; +import type { StreamCreator } from "@opennextjs/aws/http/openNextResponse"; +import type { WrapperHandler } from "@opennextjs/aws/types/overrides"; const wrapper: WrapperHandler = async (handler, converter) => { const app = express(); @@ -120,7 +120,7 @@ export default { ```typescript // dev/incrementalCache.ts -import type {IncrementalCache} from 'open-next/cache/incremental/types' +import type { IncrementalCache } from '@opennextjs/aws/types/overrides' import fs from 'node:fs/promises' import path from 'node:path' @@ -157,7 +157,7 @@ export default cache ```typescript // dev/queue.ts -import type {Queue} from 'open-next/queue/types' +import type { Queue } from '@opennextjs/aws/types/overrides' declare global { // This is declared in the global scope so that we can use it in the queue @@ -168,7 +168,7 @@ declare global { const queue: Queue = { name: 'dev-queue', send: async (message) => { - const prerenderManifest = (await import('open-next/adapters/config')).PrerenderManifest as any + const prerenderManifest = (await import('@opennextjs/aws/adapters/config')).PrerenderManifest as any const revalidateId : string = prerenderManifest.preview.previewModeId await globalThis.internalFetch(`http://localhost:3000${message.MessageBody.url}`, { method: "HEAD", diff --git a/pages/aws/inner_workings/cache_interception.mdx b/pages/aws/inner_workings/cache_interception.mdx index d0fbb1e..4b834d6 100644 --- a/pages/aws/inner_workings/cache_interception.mdx +++ b/pages/aws/inner_workings/cache_interception.mdx @@ -16,7 +16,7 @@ To enable cache interception, you need to add `enableCacheInterception` option i ```ts // open-next.config.ts -import type { OpenNextConfig } from 'open-next/types/open-next'; +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next'; const config = { default: { }, @@ -24,7 +24,7 @@ const config = { enableCacheInterception: true, }, } satisfies OpenNextConfig; - + export default config; ```