Skip to content
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

docs: add documentation on minimizing lambda bundle #167

Merged
merged 3 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion docs/pages/common_issues.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,10 @@ If you are using sentry, API routes returns empty body. You could try configurin

#### My ISR page has this cache-control header `s-maxage=2, stale-while-revalidate=2592000`

Given how ISR works, while waiting for the revalidation to happen, the page will be served using this cache control header. This prevent your server from being overloaded by a lot of requests while the revalidation is done. You can read more about it [here](/inner_workings/isr).
Given how ISR works, while waiting for the revalidation to happen, the page will be served using this cache control header. This prevent your server from being overloaded by a lot of requests while the revalidation is done. You can read more about it [here](/inner_workings/isr).

#### Unzipped size must be smaller than 262144000 bytes

AWS Lambda has an unzipped size limit of 250MB. If your app is over this limit, then it is most likely using a node_module library that is too large for serverless or there is a large dev dependency getting bundled.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add that what's important is the .open-next/server-function folder, and the rest are mostly irrelevant.
We could also add that a big bundle size will increase cold start a lot

For example, `pdfjs` has `canvas` optional dependency which takes up 180MB. For more details, [read me](/common_issues/bundle_size).
Note: a large bundle size will increase cold start significantly.
55 changes: 55 additions & 0 deletions docs/pages/common_issues/bundle_size.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {Callout} from 'nextra/components'


#### Reducing Bundle Size

Next will incorrectly trace dev dependencies to be included in the output `node_modules`, which will significantly increase the lambda bundle. For example, the @swc/core-\* binary is ~33MB!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With 13.5.1+ they probably will not even end up in node_modules, a big part is now bundled by next and may end up in one of the bundle

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I built w/ 13.5.4 and the core-darwin-arm64 binary was still there unfortunately


Add this to your next.config.js to help minimize the lambda bundle size:

```typescript
outputFileTracingExcludes: {
'*': [
'@swc/core',
'esbuild',
'uglify-js',
'watchpack',
'webassemblyjs',
'sharp'
],
},
```

<Callout type="warning" emoji="⚠️">
NextJS currently doesn't expose `outputFileTracingExcludes` as an environmental variable so `open-next`cannot programmatically set this like it does for`output`and`outputFileTracingRoot`.
Currently, next uses `webpack` to trace server actions, so you shouldn't add `webpack` to the excludes list, otherwise it will break server actions.
</Callout>

#### Unzipped size must be smaller than 262144000 bytes

To identify the module that's taking up too much space (and isn't serverless friendly):

```bash
du -hs .open-next/server-function/node_modules/* | sort -rh
```

If your app requires the offending library, then consider moving your business logic of the `api` to its own lambda, eg: `/api/v2` => `Api Lambda`

<Callout type="info" emoji="ℹ️">
There is a [PR](https://github.com/sst/open-next/pull/242) to remove some dev dependency from the output node_modules but that requires more testing before it can merge.
</Callout>

#### Common issues

##### Sharp

`sharp` is not needed outside of the `Image Optimization` function so you should not have it as a dependency. But if you are depending on `sharp`, be sure to install it with the correct flags for your lambda.
eg: `--arch=arm64 --platform=linux --target=18 --libc=glibc`

##### pdfjs

If you need to use pdfjs, you should install it with `npm i pdfjs-dist--no-optional` because the optional dep: `canvas` takes about 180MB.

##### Others

Please open an issue or let us know on discord if there are any other modules that are causing issues.
24 changes: 20 additions & 4 deletions packages/tests-e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ The 3 permutations are:

Their respective `tests/` folders are:

1. [appDirOnly](./tests/appDirOnly)
2. [pagesOnly](./tests/pagesOnly)
3. [appDirAndPages](./tests//appDirAndPages)
1. [appRouter](./tests/appDirOnly)
2. [pagesRouter](./tests/pagesOnly)
3. [appPagesRouter](./tests//appDirAndPages)

Their respective `packages/` are located at:

Expand All @@ -22,9 +22,25 @@ Their respective `packages/` are located at:

The GitHub actions will trigger the [e2e test](/.github/workflows//e2e.yml), which deploys the app in the [Example](/example/) folder. The deploy command is:

```
### Running the tests against the deployed app

1. Deploy the app
```bash
cd examples/sst
npx sst deploy --stage e2e
```
2. Export the URLS
```bash
export APP_ROUTER_URL=$(jq -r '.["e2e-example-AppRouter"].url' .sst/outputs.json)
export PAGES_ROUTER_URL=$(jq -r '.["e2e-example-PagesRouter"].url' .sst/outputs.json)
export APP_PAGES_ROUTER_URL=$(jq -r '.["e2e-example-AppPagesRouter"].url' .sst/outputs.json)
```
3. Run the test
```bash
cd ../packages/tests-e2e
npm run e2e:dev
```


## Gotchas

Expand Down