-
Notifications
You must be signed in to change notification settings - Fork 151
OpenNext V3 #402
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
OpenNext V3 #402
Changes from all commits
Commits
Show all changes
107 commits
Select commit
Hold shift + click to select a range
a420d9a
created basic config file
conico974 c2f29a8
basic wrapper and converter implementation
conico974 3379459
Minimal response writable
conico974 788913e
build config
conico974 b20f0b5
change response to transform to allow to use pipeline
conico974 a874fd7
fix streaming for v3
conico974 e7fe515
compression support
conico974 a5622de
better docker handler
conico974 26b3386
add converter for apigw-v1 & cloudfront
conico974 a9375ec
overridable queue
conico974 423831a
overridable s3 cache
conico974 70d3d64
overridable tag cache
conico974 6c10eed
prebuild middleware
conico974 14dbaac
refactor routing and middleware
conico974 5199eb9
big refactoring
conico974 8413270
refactor: cleanup plugins
conico974 a063596
make other lambdas overridable as well
conico974 8dabff0
externalMiddleware
conico974 2630bb7
improve plugins
conico974 51b5d46
fix proxy request and make it work with streaming
conico974 bac04a2
bugfix
conico974 df1142b
fix host
conico974 53b95d8
refactor wrapper
conico974 5b69d2f
generate basic dockerfile
conico974 a3dcb26
Only build open-next config once
conico974 a50cdf7
generate basic output file for IAC to use
conico974 d422b0b
basic splitting
conico974 3763bab
bundled next server
conico974 a5995db
fix external middleware cloudfront
conico974 6c1cbcf
fix image adapter rebase
conico974 23bdd78
couple of fix for node
conico974 d4aa85f
package version
conico974 cc9dcbb
support for warmer with splitted fn
conico974 7c4145d
basic support for edge runtime
conico974 132f3d5
external middleware support rewrite between splitted servers
conico974 65bec91
fix alias
conico974 09d023c
Merge branch 'feat/splitting' into v3-rc
conico974 7a20b15
update package.json
conico974 e864df2
use AsyncLocalStorage to scope lastModified to a single request
conico974 6f9a987
merge upstream/main
conico974 142aac3
Add basic validation
conico974 9d03aec
fix EISDIR issue with copying traced symlink
conico974 2f3bd61
added override name to the output for better IAC support
conico974 6b64a1d
rename BuildOptions
conico974 618d1ea
normalize locale path before passing to middleware
conico974 809ae1a
Copy necessary static files
conico974 8076ae6
fix issues with fallback and i18n in page router
conico974 e643578
Add a big warning for build on windows
conico974 770ac8a
fix for cloudflare workers
conico974 09b7b54
add wasm fils and assets
conico974 5daa00d
fix 14.1 cache
conico974 e96f69d
fix wasm import node
conico974 cb8c980
Merge branch 'feat/splitting' into v3-rc
conico974 94fde9f
update version
conico974 0af277a
merge upstream
conico974 51ba372
make open-next.config.ts optional
conico974 b86860c
Merge branch 'feat/splitting' into v3-rc
conico974 aa97c43
Fix cannot write default config file b/c folder not created (#364)
fwang 12bf5d2
fix for monorepo
conico974 1a420eb
fix for output for dynamodb provider
conico974 b2879f6
fix dynamoProvider, skipTrailingSlash, weird ISR deduplication issue
conico974 4a55c2b
little improvement to streaming in lambda
conico974 8dc9e73
fix another monorepo error
conico974 2adb4ab
e2e fixes for v3 rc
conico974 e1a9589
update version
conico974 68858bb
Not use custom-resource converter for dynamodb seeding adapter (#365)
fwang 2357429
fix fallback false for route without i18n
conico974 46562b1
version package update
conico974 429914a
Squashed commit of the following:
conico974 5dcb4c2
fix for next 12
conico974 8be4647
add support for basePath
conico974 be93d3b
allow customization of sharp runtime
conico974 63dc3b2
updated edge converter to match behaviour of lambda
conico974 3a489ad
update version
conico974 356a573
fix monorepo
conico974 2932436
improved streaming
conico974 f1b2b78
update version
conico974 2ab1717
fix open-next config build that depends on node
conico974 a2e5491
fix crypto middleware node 20
conico974 51a2639
Sync
conico974 059db68
fix resolve in image optimization
conico974 ae46f82
add better error when edge runtime is used inside node
conico974 1992b3f
update version
conico974 52a5127
fix null error on lambda
conico974 790881d
update version
conico974 9cff08a
fix 500 on aws-lambda wrapper
conico974 7f5ba6f
update version
conico974 daaeb38
fix duplex for request in node
conico974 90c59d9
fix & refactor middleware response headers
conico974 93ee01f
update version
conico974 245c139
Sync
conico974 e498e28
update version
conico974 c782117
removed specific lamda streaming hack
conico974 9f7e108
add geo in middleware
conico974 3751bf7
added helpers function for config file
conico974 d0c87c3
fix for 14.2
conico974 370547b
update version
conico974 905a6e4
fix redirect lambda streaming
conico974 8a822cb
fix e2e tests
conico974 fbfca43
test: improve reliability of test for revalidateTag
conico974 dae9d98
update version
conico974 965a014
Sync
conico974 1df7d78
review fix
conico974 050b8f5
fix cookies in streaming
conico974 9cb86cf
make all write to ddb chunked
conico974 dbb96cf
changeset
conico974 52641c1
fix e2e
conico974 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
--- | ||
"open-next": major | ||
--- | ||
|
||
OpenNext V3 | ||
|
||
This is the V3 of OpenNext. It includes some breaking changes and cannot be used as a drop-in replacement for V2. If your IAC is using OpenNext V2, you will need to update it to use V3. | ||
|
||
If you are using OpenNext V2, please refer to the [migration guide](https://open-next.js.org/migration#from-opennext-v2) to upgrade to V3. | ||
|
||
### New Features | ||
|
||
- Add support for function splitting | ||
- Add support for external middleware | ||
- Custom config file support : `open-next.config.ts` | ||
- Support for other deployment targets than lambda (Node.js, Docker and partial support for Cloudflare Workers) | ||
- Allow for customizing the outputs bundle : | ||
- Wrapper | ||
- Converter | ||
- Incremental Cache (Fetch cache and HTML/JSON/RSC cache) | ||
- Tag Cache | ||
- Queue (Used to trigger ISR revalidation) | ||
- Origin Resolver (Only for external middleware) | ||
- Image Loader (Only for image optimization) | ||
- Invoke function (For the warmer function) | ||
- Create an `open-next.output.json` file for easier integration with IAC tools | ||
|
||
### Breaking Changes | ||
|
||
- Edge runtime don't work out of the box anymore. You need to deploy them on a separate function see [the config for more info](https://open-next.js.org/config) | ||
- Output directory structure has changed to support function splitting | ||
- Removed build arguments in favor of `open-next.config.ts` | ||
|
||
### Internal Changes | ||
|
||
- Use OpenNextNodeResponse instead of ServerResponse (It uses transform stream to properly handle the stream) | ||
- Big refactor of the codebase to support function splitting | ||
- Added new plugins to support the new features and make the codebase more modular |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,4 +2,4 @@ | |
"caching": "Caching (ISR/SSG)", | ||
"components": "Main Components", | ||
"architecture": "Default Architecture" | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"index": "What's new", | ||
"config": "Configuration file", | ||
"reference-implementation": "Reference Construct", | ||
"requirements": "Requirements", | ||
"override": "Advanced - Create your own override" | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
Here is a simple 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, just look at the source file | ||
|
||
```ts | ||
import type { OpenNextConfig } from 'open-next/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 | ||
// for normal lambda as in open-next v2 | ||
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({ | ||
send: async (message) => { | ||
//Your custom code here | ||
} | ||
}) | ||
}, | ||
}, | ||
// Below we define the functions that we want to deploy in a different server | ||
functions: { | ||
ssr: { | ||
routes: [ | ||
"app/api/isr/route", "app/api/sse/route", "app/api/revalidateTag/route", // app dir Api routes | ||
"app/route1/page", "app/route2/page", // app dir pages | ||
"pages/route3" // page dir pages | ||
], // For app dir, you need to include route|page, no need to include layout or loading | ||
patterns: ['api/*', 'route1', 'route2', 'route3'], // patterns needs to be in a cloudfront compatible format, this will be used to generate the output | ||
override: { | ||
wrapper: "aws-lambda-streaming", | ||
}, | ||
experimentalBundledNextServer: true // This enables the bundled next server which is faster and reduce the size of the server | ||
}, | ||
pageSsr: { | ||
routes: ["pages/pageSsr"], // For page dir routes should be in the form `pages/${route}` without the extension, it should match the filesystem | ||
patterns: [ 'pageSsr', "_next/data/BUILD_ID/pageSsr.json"], | ||
override: { | ||
wrapper: "node", | ||
converter: "node", | ||
// This is necessary to generate the dockerfile and for the implementation to know that it needs to deploy on docker | ||
generateDockerfile: true, | ||
}, | ||
}, | ||
edge: { | ||
conico974 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
runtime: "edge", | ||
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. | ||
// 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. | ||
middleware: { | ||
external: true | ||
} | ||
buildCommand: "echo 'hello world'", | ||
} satisfies OpenNextConfig | ||
|
||
export default config; | ||
export type Config = typeof config | ||
``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import { Callout } from 'nextra/components' | ||
|
||
<Callout type="warning" emoji="⚠️"> | ||
|
||
`open-next@3.0.0-rc.3` is here!!! Please report any issues you find on [discord](https://discord.com/channels/983865673656705025/1164872233223729152) or on the github [PR](https://github.com/sst/open-next/pull/327) | ||
|
||
This is a release candidate, it is mostly ready for production (You might still experience some quirks). We are looking for feedback on this release, so please try it out and let us know what you think. See [getting started](#get-started) to quickly test it. | ||
|
||
It also requires an updated version of the IAC tools that you use, see the sst PR [here](https://github.com/sst/sst/pull/3567) for more information. | ||
|
||
You could also use SST Ion which should support it out of the box pretty soon. See [here for more info](https://github.com/sst/ion) or in the [ion discord](https://discord.com/channels/983865673656705025/1177071497974648952). | ||
</Callout> | ||
|
||
## What's new in V3? | ||
|
||
- Rewritten server (We moved from the serverless-http `ServerResponse` into our own version which respect nodejs stream) | ||
- A new `open-next.config.ts` file to configure your project | ||
- Native support for aws lambda, aws lambda streaming, lambda@edge, node and docker | ||
- In this `open-next.config.ts` you can now override a lot of things which allow for more customization: | ||
- Wrapper component | ||
- Converter component | ||
- Incremental Cache | ||
- Tag Cache | ||
- Queue | ||
- Custom warmer function | ||
- Custom revalidation function | ||
- Custom loader for image optimization | ||
- Custom initialization function | ||
|
||
- Allow for splitting, you can now split your next app into multiple servers, which could each have their own configuration | ||
- Allow to move the middleware/routing part in a separate lambda or cloudflare workers in front of your server functions | ||
- An experimental bundled `NextServer` could be used which can reduce the size of your lambda by up to 24 MB | ||
- Experimental support for the `edge` runtime of next with some limitations: | ||
- Only app router for now | ||
- Only 1 route per function | ||
- Works fine in node, only for api route in cloudflare workers | ||
- No support for `revalidateTag` or `revalidatePath` for now | ||
|
||
## Get started | ||
|
||
The easiest way to get started is to use the [reference implementation construct](/v3/reference-implementation). Copy this reference implementation into your project and then use it like that in your sst or cdk project: | ||
|
||
```ts | ||
import { OpenNextCdkReferenceImplementation } from "path/to/reference-implementation" | ||
|
||
const site = new OpenNextCdkReferenceImplementation(stack, "site", { | ||
openNextPath: ".open-next", | ||
}) | ||
``` | ||
|
||
You also need to create an `open-next.config.ts` file in your project root, you can find more info [here](/v3/config). | ||
|
||
A very simple example of this file could be: | ||
|
||
```ts | ||
import type { OpenNextConfig } from 'open-next/types/open-next' | ||
const config = { | ||
default: { | ||
|
||
} | ||
} | ||
export default config; | ||
``` | ||
|
||
Then you need to run `npx open-next@3.0.0-rc.3 build` to build your project before running the `sst deploy` or `cdk deploy` command to deploy your project. | ||
|
||
In V3 `open-next build` don't accept any arguments, all the args are passed in the `open-next.config.ts` file. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
In this version of open-next, you could override a lot of the default behaviour. | ||
|
||
For some real example of how to override each behaviour: | ||
- [Wrapper](https://github.com/conico974/open-next/blob/feat/splitting/packages/open-next/src/wrappers/aws-lambda.ts) | ||
- [Converter](https://github.com/conico974/open-next/blob/feat/splitting/packages/open-next/src/converters/aws-apigw-v2.ts) | ||
- [IncrementalCache](https://github.com/conico974/open-next/blob/feat/splitting/packages/open-next/src/cache/incremental/s3.ts) | ||
- [TagCache]( | ||
https://github.com/conico974/open-next/blob/feat/splitting/packages/open-next/src/cache/tag/dynamoDb.ts | ||
) | ||
- [Queue]( | ||
https://github.com/conico974/open-next/blob/feat/splitting/packages/open-next/src/queue/sqs.ts | ||
) | ||
|
||
This means it could allow people to write their own custom open-next. | ||
For example you could create a custom `withGcp` plugin to allow to deploy open-next on GCP functions | ||
|
||
A boilerplate for such a plugin could look like this (This is not real code): | ||
|
||
```ts | ||
|
||
import { OpenNextConfig } from "open-next/types/open-next"; | ||
|
||
function withGcp(config: TrimmedDownConfig): OpenNextConfig { | ||
return { | ||
default: { | ||
override: { | ||
wrapper: async () => (await import("./gcp-wrapper")).default, | ||
converter: async () => (await import("./gcp-converter")).default, | ||
incrementalCache: async () => (await import("./gcp-incremental-cache")).default, | ||
tagCache: async () => (await import("./gcp-tag-cache")).default, | ||
queue: async () => (await import("./gcp-queue")).default, | ||
}, | ||
...config.default, | ||
}, | ||
functions: { | ||
// Same as default but for each splitted function | ||
//... | ||
} | ||
warmer: { | ||
override: { | ||
wrapper: async () => (await import("./gcp-wrapper")).default, | ||
converter: async () => (await import("./gcp-converter")).default, | ||
}, | ||
invokeFunction: async () => (await import("./gcp-invoke-function")).default, | ||
}, | ||
revalidate: { | ||
override: { | ||
wrapper: async () => (await import("./gcp-wrapper")).default, | ||
converter: async () => (await import("./gcp-queue-converter")).default, | ||
}, | ||
}, | ||
imageOptimization: { | ||
override: { | ||
wrapper: async () => (await import("./gcp-wrapper")).default, | ||
converter: async () => (await import("./gcp-converter")).default, | ||
}, | ||
loader: async () => (await import("./gcp-object-loader")).default, | ||
}, | ||
} | ||
} | ||
``` | ||
|
||
Using this plugin would look like this inside `open-next.config.ts`: | ||
|
||
```ts | ||
import { withGcp } from "./with-gcp"; | ||
const config = withGcp({ | ||
default: { | ||
// ... | ||
}, | ||
}); | ||
|
||
export default config; | ||
``` |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this correct:
ssr
=> appDirpageSsr
=> pagesDirI'm wondering if people would easily understand/get this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not necessarily, you can give whatever name you want here, and you can mix app and page dir as much as you want. The
ssr
functions for example has apage/route3
routeYou can also have as many different functions as you want
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops had a dyslexic typo, should have been
is this correct
, notthis is correct
... updated comment.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know how to properly explain these things, but i think with some time and people asking questions about it, we'll figure a proper way to explain it.