Skip to content

Commit

Permalink
sync aws doc with code (#34)
Browse files Browse the repository at this point in the history
Co-authored-by: conico974 <[email protected]>
  • Loading branch information
vicb and conico974 authored Nov 26, 2024
1 parent 61d651b commit c0d3199
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 75 deletions.
38 changes: 19 additions & 19 deletions pages/aws/config/custom_overrides.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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.

<Callout>
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']
```
Expand All @@ -13,22 +13,22 @@ 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.js'
import { Config } from 'sst/node/Config'
const mySecretKey = Config.YOUR_SECRET_KEY

export default {
convertFrom: async (event) => {
const result = await converter.convertFrom(event)
return {
...result,
...result,
headers: {
...result.headers,
'inserted-in-converter': '1',
Expand All @@ -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.js'

const config = {
default: {
Expand All @@ -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 {
Expand All @@ -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.js'
const config = {
default: {
override: {
Expand All @@ -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 () => {
Expand All @@ -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',{
Expand All @@ -129,16 +129,16 @@ export function middleware(request: NextRequest) {

// ... your code here
}

```


### Use middy.js with the wrapper

```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.js'
import middy from '@middy/core'
import httpSecurityHeaders from '@middy/http-security-headers'

Expand All @@ -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.js'
const config = {
default: {
override: {
Expand All @@ -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.js";
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.js";
import type { WrapperHandler } from "@opennextjs/aws/types/overrides.js";

type AwsLambdaEvent =
| APIGatewayProxyEventV2
Expand Down Expand Up @@ -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.js'
const config = {
default: {
override: {
Expand Down
28 changes: 14 additions & 14 deletions pages/aws/config/full_example.mdx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
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)

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.js'
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({
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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",
Expand Down
42 changes: 21 additions & 21 deletions pages/aws/config/nx.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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}
**/
Expand All @@ -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.js';

const config = {
default: {},
Expand All @@ -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",
Expand All @@ -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
Expand All @@ -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": [
Expand Down Expand Up @@ -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
/// <reference path="./.sst/platform/config.d.ts" />
Expand All @@ -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.
Expand Down Expand Up @@ -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
{
Expand All @@ -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",
Expand All @@ -234,7 +234,7 @@ this will resolve the type issues and initialise SST.
+ "args": ["--stage=staging"]
+ },
+ "dev": {
+ "args": ["--stage=development"]
+ "args": ["--stage=development"]
+ }
+ }
+ }
Expand All @@ -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
```
Loading

0 comments on commit c0d3199

Please sign in to comment.