From 7d4d08a6fd37f1a786a35e37cbace0fb258a1f78 Mon Sep 17 00:00:00 2001 From: Mischa Spiegelmock <me@mish.dev> Date: Thu, 22 Dec 2022 09:41:11 +0200 Subject: [PATCH] fix: Output paths (#62) * Clearer paths for output * chore: self mutation Signed-off-by: github-actions <github-actions@github.com> * Fixing server output path * chore: self mutation Signed-off-by: github-actions <github-actions@github.com> * Fix server handler path in lambda function * comment Signed-off-by: github-actions <github-actions@github.com> Co-authored-by: github-actions <github-actions@github.com> --- API.md | 170 ++++++++++++++++++++++++++++++++++++++++---- src/NextjsBase.ts | 8 ++- src/NextjsBuild.ts | 55 ++++++++++++-- src/NextjsLambda.ts | 11 ++- 4 files changed, 219 insertions(+), 25 deletions(-) diff --git a/API.md b/API.md index 235fab0a..8ed6cf31 100644 --- a/API.md +++ b/API.md @@ -1520,11 +1520,14 @@ Any object. | <code><a href="#cdk-nextjs-standalone.NextjsBuild.property.node">node</a></code> | <code>constructs.Node</code> | The tree node. | | <code><a href="#cdk-nextjs-standalone.NextjsBuild.property.buildPath">buildPath</a></code> | <code>string</code> | The path to the directory where the server build artifacts are stored. | | <code><a href="#cdk-nextjs-standalone.NextjsBuild.property.nextDir">nextDir</a></code> | <code>string</code> | *No description.* | +| <code><a href="#cdk-nextjs-standalone.NextjsBuild.property.nextDirRelative">nextDirRelative</a></code> | <code>string</code> | Relative path from project root to nextjs project. | | <code><a href="#cdk-nextjs-standalone.NextjsBuild.property.nextPublicDir">nextPublicDir</a></code> | <code>string</code> | Public static files. | -| <code><a href="#cdk-nextjs-standalone.NextjsBuild.property.nextStandaloneBuildDir">nextStandaloneBuildDir</a></code> | <code>string</code> | NextJS project inside of standalone build. | -| <code><a href="#cdk-nextjs-standalone.NextjsBuild.property.nextStandaloneDir">nextStandaloneDir</a></code> | <code>string</code> | Entire NextJS build output directory. | +| <code><a href="#cdk-nextjs-standalone.NextjsBuild.property.nextStandaloneBuildDir">nextStandaloneBuildDir</a></code> | <code>string</code> | NextJS build inside of standalone build. | +| <code><a href="#cdk-nextjs-standalone.NextjsBuild.property.nextStandaloneDir">nextStandaloneDir</a></code> | <code>string</code> | NextJS project inside of standalone build. | | <code><a href="#cdk-nextjs-standalone.NextjsBuild.property.nextStaticDir">nextStaticDir</a></code> | <code>string</code> | Static files containing client-side code. | +| <code><a href="#cdk-nextjs-standalone.NextjsBuild.property.projectRoot">projectRoot</a></code> | <code>string</code> | *No description.* | | <code><a href="#cdk-nextjs-standalone.NextjsBuild.property.props">props</a></code> | <code><a href="#cdk-nextjs-standalone.NextjsBuildProps">NextjsBuildProps</a></code> | *No description.* | +| <code><a href="#cdk-nextjs-standalone.NextjsBuild.property.standaloneDir">standaloneDir</a></code> | <code>string</code> | Entire NextJS build output directory. | | <code><a href="#cdk-nextjs-standalone.NextjsBuild.property.tempBuildDir">tempBuildDir</a></code> | <code>string</code> | *No description.* | --- @@ -1563,6 +1566,20 @@ public readonly nextDir: string; --- +##### `nextDirRelative`<sup>Required</sup> <a name="nextDirRelative" id="cdk-nextjs-standalone.NextjsBuild.property.nextDirRelative"></a> + +```typescript +public readonly nextDirRelative: string; +``` + +- *Type:* string + +Relative path from project root to nextjs project. + +e.g. 'web' or 'packages/web' or '.' + +--- + ##### `nextPublicDir`<sup>Required</sup> <a name="nextPublicDir" id="cdk-nextjs-standalone.NextjsBuild.property.nextPublicDir"></a> ```typescript @@ -1585,7 +1602,7 @@ public readonly nextStandaloneBuildDir: string; - *Type:* string -NextJS project inside of standalone build. +NextJS build inside of standalone build. Contains server code and manifests. @@ -1599,9 +1616,9 @@ public readonly nextStandaloneDir: string; - *Type:* string -Entire NextJS build output directory. +NextJS project inside of standalone build. -Contains server and client code and manifests. +Contains .next build and server code and traced dependencies. --- @@ -1617,6 +1634,16 @@ Static files containing client-side code. --- +##### `projectRoot`<sup>Required</sup> <a name="projectRoot" id="cdk-nextjs-standalone.NextjsBuild.property.projectRoot"></a> + +```typescript +public readonly projectRoot: string; +``` + +- *Type:* string + +--- + ##### `props`<sup>Required</sup> <a name="props" id="cdk-nextjs-standalone.NextjsBuild.property.props"></a> ```typescript @@ -1627,6 +1654,20 @@ public readonly props: NextjsBuildProps; --- +##### `standaloneDir`<sup>Required</sup> <a name="standaloneDir" id="cdk-nextjs-standalone.NextjsBuild.property.standaloneDir"></a> + +```typescript +public readonly standaloneDir: string; +``` + +- *Type:* string + +Entire NextJS build output directory. + +Contains server and client code and manifests. + +--- + ##### `tempBuildDir`<sup>Required</sup> <a name="tempBuildDir" id="cdk-nextjs-standalone.NextjsBuild.property.tempBuildDir"></a> ```typescript @@ -2639,6 +2680,7 @@ const imageOptimizationProps: ImageOptimizationProps = { ... } | <code><a href="#cdk-nextjs-standalone.ImageOptimizationProps.property.environment">environment</a></code> | <code>{[ key: string ]: string}</code> | Custom environment variables to pass to the NextJS build and runtime. | | <code><a href="#cdk-nextjs-standalone.ImageOptimizationProps.property.isPlaceholder">isPlaceholder</a></code> | <code>boolean</code> | Skip building app and deploy a placeholder. | | <code><a href="#cdk-nextjs-standalone.ImageOptimizationProps.property.nodeEnv">nodeEnv</a></code> | <code>string</code> | Optional value for NODE_ENV during build and runtime. | +| <code><a href="#cdk-nextjs-standalone.ImageOptimizationProps.property.projectRoot">projectRoot</a></code> | <code>string</code> | Root of your project, if different from `nextjsPath`. | | <code><a href="#cdk-nextjs-standalone.ImageOptimizationProps.property.quiet">quiet</a></code> | <code>boolean</code> | Less build output. | | <code><a href="#cdk-nextjs-standalone.ImageOptimizationProps.property.tempBuildDir">tempBuildDir</a></code> | <code>string</code> | Directory to store temporary build files in. | | <code><a href="#cdk-nextjs-standalone.ImageOptimizationProps.property.bucket">bucket</a></code> | <code>aws-cdk-lib.aws_s3.IBucket</code> | The S3 bucket holding application images. | @@ -2672,7 +2714,7 @@ public readonly buildPath: string; The directory to execute `npm run build` from. -By default, it uses `nextjsPath`. +By default, it is `nextjsPath`. Can be overridden, particularly useful for monorepos where `build` is expected to run at the root of the project. @@ -2729,6 +2771,20 @@ Optional value for NODE_ENV during build and runtime. --- +##### `projectRoot`<sup>Optional</sup> <a name="projectRoot" id="cdk-nextjs-standalone.ImageOptimizationProps.property.projectRoot"></a> + +```typescript +public readonly projectRoot: string; +``` + +- *Type:* string + +Root of your project, if different from `nextjsPath`. + +Defaults to current working directory. + +--- + ##### `quiet`<sup>Optional</sup> <a name="quiet" id="cdk-nextjs-standalone.ImageOptimizationProps.property.quiet"></a> ```typescript @@ -2870,6 +2926,7 @@ const nextjsAssetsDeploymentProps: NextjsAssetsDeploymentProps = { ... } | <code><a href="#cdk-nextjs-standalone.NextjsAssetsDeploymentProps.property.environment">environment</a></code> | <code>{[ key: string ]: string}</code> | Custom environment variables to pass to the NextJS build and runtime. | | <code><a href="#cdk-nextjs-standalone.NextjsAssetsDeploymentProps.property.isPlaceholder">isPlaceholder</a></code> | <code>boolean</code> | Skip building app and deploy a placeholder. | | <code><a href="#cdk-nextjs-standalone.NextjsAssetsDeploymentProps.property.nodeEnv">nodeEnv</a></code> | <code>string</code> | Optional value for NODE_ENV during build and runtime. | +| <code><a href="#cdk-nextjs-standalone.NextjsAssetsDeploymentProps.property.projectRoot">projectRoot</a></code> | <code>string</code> | Root of your project, if different from `nextjsPath`. | | <code><a href="#cdk-nextjs-standalone.NextjsAssetsDeploymentProps.property.quiet">quiet</a></code> | <code>boolean</code> | Less build output. | | <code><a href="#cdk-nextjs-standalone.NextjsAssetsDeploymentProps.property.tempBuildDir">tempBuildDir</a></code> | <code>string</code> | Directory to store temporary build files in. | | <code><a href="#cdk-nextjs-standalone.NextjsAssetsDeploymentProps.property.bucket">bucket</a></code> | <code>aws-cdk-lib.aws_s3.IBucket</code> | Properties for the S3 bucket containing the NextJS assets. | @@ -2904,7 +2961,7 @@ public readonly buildPath: string; The directory to execute `npm run build` from. -By default, it uses `nextjsPath`. +By default, it is `nextjsPath`. Can be overridden, particularly useful for monorepos where `build` is expected to run at the root of the project. @@ -2961,6 +3018,20 @@ Optional value for NODE_ENV during build and runtime. --- +##### `projectRoot`<sup>Optional</sup> <a name="projectRoot" id="cdk-nextjs-standalone.NextjsAssetsDeploymentProps.property.projectRoot"></a> + +```typescript +public readonly projectRoot: string; +``` + +- *Type:* string + +Root of your project, if different from `nextjsPath`. + +Defaults to current working directory. + +--- + ##### `quiet`<sup>Optional</sup> <a name="quiet" id="cdk-nextjs-standalone.NextjsAssetsDeploymentProps.property.quiet"></a> ```typescript @@ -3071,6 +3142,7 @@ const nextjsBaseProps: NextjsBaseProps = { ... } | <code><a href="#cdk-nextjs-standalone.NextjsBaseProps.property.environment">environment</a></code> | <code>{[ key: string ]: string}</code> | Custom environment variables to pass to the NextJS build and runtime. | | <code><a href="#cdk-nextjs-standalone.NextjsBaseProps.property.isPlaceholder">isPlaceholder</a></code> | <code>boolean</code> | Skip building app and deploy a placeholder. | | <code><a href="#cdk-nextjs-standalone.NextjsBaseProps.property.nodeEnv">nodeEnv</a></code> | <code>string</code> | Optional value for NODE_ENV during build and runtime. | +| <code><a href="#cdk-nextjs-standalone.NextjsBaseProps.property.projectRoot">projectRoot</a></code> | <code>string</code> | Root of your project, if different from `nextjsPath`. | | <code><a href="#cdk-nextjs-standalone.NextjsBaseProps.property.quiet">quiet</a></code> | <code>boolean</code> | Less build output. | | <code><a href="#cdk-nextjs-standalone.NextjsBaseProps.property.tempBuildDir">tempBuildDir</a></code> | <code>string</code> | Directory to store temporary build files in. | @@ -3100,7 +3172,7 @@ public readonly buildPath: string; The directory to execute `npm run build` from. -By default, it uses `nextjsPath`. +By default, it is `nextjsPath`. Can be overridden, particularly useful for monorepos where `build` is expected to run at the root of the project. @@ -3157,6 +3229,20 @@ Optional value for NODE_ENV during build and runtime. --- +##### `projectRoot`<sup>Optional</sup> <a name="projectRoot" id="cdk-nextjs-standalone.NextjsBaseProps.property.projectRoot"></a> + +```typescript +public readonly projectRoot: string; +``` + +- *Type:* string + +Root of your project, if different from `nextjsPath`. + +Defaults to current working directory. + +--- + ##### `quiet`<sup>Optional</sup> <a name="quiet" id="cdk-nextjs-standalone.NextjsBaseProps.property.quiet"></a> ```typescript @@ -3203,6 +3289,7 @@ const nextjsBuildProps: NextjsBuildProps = { ... } | <code><a href="#cdk-nextjs-standalone.NextjsBuildProps.property.environment">environment</a></code> | <code>{[ key: string ]: string}</code> | Custom environment variables to pass to the NextJS build and runtime. | | <code><a href="#cdk-nextjs-standalone.NextjsBuildProps.property.isPlaceholder">isPlaceholder</a></code> | <code>boolean</code> | Skip building app and deploy a placeholder. | | <code><a href="#cdk-nextjs-standalone.NextjsBuildProps.property.nodeEnv">nodeEnv</a></code> | <code>string</code> | Optional value for NODE_ENV during build and runtime. | +| <code><a href="#cdk-nextjs-standalone.NextjsBuildProps.property.projectRoot">projectRoot</a></code> | <code>string</code> | Root of your project, if different from `nextjsPath`. | | <code><a href="#cdk-nextjs-standalone.NextjsBuildProps.property.quiet">quiet</a></code> | <code>boolean</code> | Less build output. | | <code><a href="#cdk-nextjs-standalone.NextjsBuildProps.property.tempBuildDir">tempBuildDir</a></code> | <code>string</code> | Directory to store temporary build files in. | @@ -3232,7 +3319,7 @@ public readonly buildPath: string; The directory to execute `npm run build` from. -By default, it uses `nextjsPath`. +By default, it is `nextjsPath`. Can be overridden, particularly useful for monorepos where `build` is expected to run at the root of the project. @@ -3289,6 +3376,20 @@ Optional value for NODE_ENV during build and runtime. --- +##### `projectRoot`<sup>Optional</sup> <a name="projectRoot" id="cdk-nextjs-standalone.NextjsBuildProps.property.projectRoot"></a> + +```typescript +public readonly projectRoot: string; +``` + +- *Type:* string + +Root of your project, if different from `nextjsPath`. + +Defaults to current working directory. + +--- + ##### `quiet`<sup>Optional</sup> <a name="quiet" id="cdk-nextjs-standalone.NextjsBuildProps.property.quiet"></a> ```typescript @@ -3492,6 +3593,7 @@ const nextjsDistributionProps: NextjsDistributionProps = { ... } | <code><a href="#cdk-nextjs-standalone.NextjsDistributionProps.property.environment">environment</a></code> | <code>{[ key: string ]: string}</code> | Custom environment variables to pass to the NextJS build and runtime. | | <code><a href="#cdk-nextjs-standalone.NextjsDistributionProps.property.isPlaceholder">isPlaceholder</a></code> | <code>boolean</code> | Skip building app and deploy a placeholder. | | <code><a href="#cdk-nextjs-standalone.NextjsDistributionProps.property.nodeEnv">nodeEnv</a></code> | <code>string</code> | Optional value for NODE_ENV during build and runtime. | +| <code><a href="#cdk-nextjs-standalone.NextjsDistributionProps.property.projectRoot">projectRoot</a></code> | <code>string</code> | Root of your project, if different from `nextjsPath`. | | <code><a href="#cdk-nextjs-standalone.NextjsDistributionProps.property.quiet">quiet</a></code> | <code>boolean</code> | Less build output. | | <code><a href="#cdk-nextjs-standalone.NextjsDistributionProps.property.tempBuildDir">tempBuildDir</a></code> | <code>string</code> | Directory to store temporary build files in. | | <code><a href="#cdk-nextjs-standalone.NextjsDistributionProps.property.imageOptFunction">imageOptFunction</a></code> | <code>aws-cdk-lib.aws_lambda.IFunction</code> | Lambda function to optimize images. | @@ -3530,7 +3632,7 @@ public readonly buildPath: string; The directory to execute `npm run build` from. -By default, it uses `nextjsPath`. +By default, it is `nextjsPath`. Can be overridden, particularly useful for monorepos where `build` is expected to run at the root of the project. @@ -3587,6 +3689,20 @@ Optional value for NODE_ENV during build and runtime. --- +##### `projectRoot`<sup>Optional</sup> <a name="projectRoot" id="cdk-nextjs-standalone.NextjsDistributionProps.property.projectRoot"></a> + +```typescript +public readonly projectRoot: string; +``` + +- *Type:* string + +Root of your project, if different from `nextjsPath`. + +Defaults to current working directory. + +--- + ##### `quiet`<sup>Optional</sup> <a name="quiet" id="cdk-nextjs-standalone.NextjsDistributionProps.property.quiet"></a> ```typescript @@ -3877,6 +3993,7 @@ const nextjsLambdaProps: NextjsLambdaProps = { ... } | <code><a href="#cdk-nextjs-standalone.NextjsLambdaProps.property.environment">environment</a></code> | <code>{[ key: string ]: string}</code> | Custom environment variables to pass to the NextJS build and runtime. | | <code><a href="#cdk-nextjs-standalone.NextjsLambdaProps.property.isPlaceholder">isPlaceholder</a></code> | <code>boolean</code> | Skip building app and deploy a placeholder. | | <code><a href="#cdk-nextjs-standalone.NextjsLambdaProps.property.nodeEnv">nodeEnv</a></code> | <code>string</code> | Optional value for NODE_ENV during build and runtime. | +| <code><a href="#cdk-nextjs-standalone.NextjsLambdaProps.property.projectRoot">projectRoot</a></code> | <code>string</code> | Root of your project, if different from `nextjsPath`. | | <code><a href="#cdk-nextjs-standalone.NextjsLambdaProps.property.quiet">quiet</a></code> | <code>boolean</code> | Less build output. | | <code><a href="#cdk-nextjs-standalone.NextjsLambdaProps.property.tempBuildDir">tempBuildDir</a></code> | <code>string</code> | Directory to store temporary build files in. | | <code><a href="#cdk-nextjs-standalone.NextjsLambdaProps.property.nextBuild">nextBuild</a></code> | <code><a href="#cdk-nextjs-standalone.NextjsBuild">NextjsBuild</a></code> | Built nextJS application. | @@ -3908,7 +4025,7 @@ public readonly buildPath: string; The directory to execute `npm run build` from. -By default, it uses `nextjsPath`. +By default, it is `nextjsPath`. Can be overridden, particularly useful for monorepos where `build` is expected to run at the root of the project. @@ -3965,6 +4082,20 @@ Optional value for NODE_ENV during build and runtime. --- +##### `projectRoot`<sup>Optional</sup> <a name="projectRoot" id="cdk-nextjs-standalone.NextjsLambdaProps.property.projectRoot"></a> + +```typescript +public readonly projectRoot: string; +``` + +- *Type:* string + +Root of your project, if different from `nextjsPath`. + +Defaults to current working directory. + +--- + ##### `quiet`<sup>Optional</sup> <a name="quiet" id="cdk-nextjs-standalone.NextjsLambdaProps.property.quiet"></a> ```typescript @@ -4046,6 +4177,7 @@ const nextjsProps: NextjsProps = { ... } | <code><a href="#cdk-nextjs-standalone.NextjsProps.property.environment">environment</a></code> | <code>{[ key: string ]: string}</code> | Custom environment variables to pass to the NextJS build and runtime. | | <code><a href="#cdk-nextjs-standalone.NextjsProps.property.isPlaceholder">isPlaceholder</a></code> | <code>boolean</code> | Skip building app and deploy a placeholder. | | <code><a href="#cdk-nextjs-standalone.NextjsProps.property.nodeEnv">nodeEnv</a></code> | <code>string</code> | Optional value for NODE_ENV during build and runtime. | +| <code><a href="#cdk-nextjs-standalone.NextjsProps.property.projectRoot">projectRoot</a></code> | <code>string</code> | Root of your project, if different from `nextjsPath`. | | <code><a href="#cdk-nextjs-standalone.NextjsProps.property.quiet">quiet</a></code> | <code>boolean</code> | Less build output. | | <code><a href="#cdk-nextjs-standalone.NextjsProps.property.tempBuildDir">tempBuildDir</a></code> | <code>string</code> | Directory to store temporary build files in. | | <code><a href="#cdk-nextjs-standalone.NextjsProps.property.defaults">defaults</a></code> | <code><a href="#cdk-nextjs-standalone.NextjsDefaultsProps">NextjsDefaultsProps</a></code> | Allows you to override defaults for the resources created by this construct. | @@ -4077,7 +4209,7 @@ public readonly buildPath: string; The directory to execute `npm run build` from. -By default, it uses `nextjsPath`. +By default, it is `nextjsPath`. Can be overridden, particularly useful for monorepos where `build` is expected to run at the root of the project. @@ -4134,6 +4266,20 @@ Optional value for NODE_ENV during build and runtime. --- +##### `projectRoot`<sup>Optional</sup> <a name="projectRoot" id="cdk-nextjs-standalone.NextjsProps.property.projectRoot"></a> + +```typescript +public readonly projectRoot: string; +``` + +- *Type:* string + +Root of your project, if different from `nextjsPath`. + +Defaults to current working directory. + +--- + ##### `quiet`<sup>Optional</sup> <a name="quiet" id="cdk-nextjs-standalone.NextjsProps.property.quiet"></a> ```typescript diff --git a/src/NextjsBase.ts b/src/NextjsBase.ts index 1e557337..98a48e8f 100644 --- a/src/NextjsBase.ts +++ b/src/NextjsBase.ts @@ -15,12 +15,18 @@ export interface NextjsBaseProps { readonly nextjsPath: string; /** - * The directory to execute `npm run build` from. By default, it uses `nextjsPath`. + * The directory to execute `npm run build` from. By default, it is `nextjsPath`. * Can be overridden, particularly useful for monorepos where `build` is expected to run * at the root of the project. */ readonly buildPath?: string; + /** + * Root of your project, if different from `nextjsPath`. + * Defaults to current working directory. + */ + readonly projectRoot?: string; + /** * Custom environment variables to pass to the NextJS build and runtime. */ diff --git a/src/NextjsBuild.ts b/src/NextjsBuild.ts index 4b749153..b2bd8513 100644 --- a/src/NextjsBuild.ts +++ b/src/NextjsBuild.ts @@ -33,9 +33,14 @@ export class NextjsBuild extends Construct { * Entire NextJS build output directory. * Contains server and client code and manifests. */ - public nextStandaloneDir: string; + public standaloneDir: string; /** * NextJS project inside of standalone build. + * Contains .next build and server code and traced dependencies. + */ + public nextStandaloneDir: string; + /** + * NextJS build inside of standalone build. * Contains server code and manifests. */ public nextStandaloneBuildDir: string; @@ -48,12 +53,18 @@ export class NextjsBuild extends Construct { * E.g. robots.txt, favicon.ico, etc. */ public nextPublicDir: string; + /** + * Relative path from project root to nextjs project. + * e.g. 'web' or 'packages/web' or '.' + */ + public nextDirRelative: string; public props: NextjsBuildProps; public tempBuildDir: string; public nextDir: string; + public projectRoot: string; constructor(scope: Construct, id: string, props: NextjsBuildProps) { super(scope, id); @@ -68,6 +79,9 @@ export class NextjsBuild extends Construct { const baseOutputDir = path.resolve(this.props.nextjsPath); if (!fs.existsSync(baseOutputDir)) throw new Error(`NextJS application not found at "${baseOutputDir}"`); + // root of project + this.projectRoot = props.projectRoot ? path.resolve(props.projectRoot) : path.resolve(); + // build app this.runNpmBuild(); @@ -77,8 +91,10 @@ export class NextjsBuild extends Construct { throw new Error(`No server build output found at "${serverBuildDir}"`); // our outputs + this.standaloneDir = this._getStandaloneDir(); this.nextStandaloneDir = this._getNextStandaloneDir(); this.nextStandaloneBuildDir = this._getNextStandaloneBuildDir(); + this.nextDirRelative = this._getNextDirRelative(); this.nextPublicDir = this._getNextPublicDir(); this.nextStaticDir = this._getNextStaticDir(); this.buildPath = this.nextStandaloneBuildDir; @@ -107,10 +123,11 @@ export class NextjsBuild extends Construct { } // build environment vars + const outputTracingRoot = this.projectRoot; const buildEnv = { ...process.env, [NEXTJS_BUILD_STANDALONE_ENV]: 'true', - [NEXTJS_BUILD_OUTPUTTRACEROOT_ENV]: path.resolve(), + [NEXTJS_BUILD_OUTPUTTRACEROOT_ENV]: outputTracingRoot, ...getBuildCmdEnvironment(this.props.environment), ...(this.props.nodeEnv ? { NODE_ENV: this.props.nodeEnv } : {}), }; @@ -138,7 +155,7 @@ export class NextjsBuild extends Construct { return listDirectory(publicDir).map((file) => path.join('/', path.relative(publicDir, file))); } - // get the path to the directory containing the nextjs project + // get the absolute path to the directory containing the nextjs project // it may be the project root or a subdirectory in a monorepo setup private _getNextDir() { const { nextjsPath } = this.props; // path to nextjs dir inside project @@ -149,13 +166,21 @@ export class NextjsBuild extends Construct { return absolutePath; } + // get relative path from root of the project to the nextjs project + // e.g. 'web' or 'packages/web' + private _getNextDirRelative() { + const absNextDir = this._getNextDir(); + const absProjectDir = this.projectRoot; + return path.relative(absProjectDir, absNextDir); + } + // .next private _getNextBuildDir() { return path.join(this._getNextDir(), NEXTJS_BUILD_DIR); } // output of nextjs standalone build - private _getNextStandaloneDir() { + private _getStandaloneDir() { const nextDir = this._getNextBuildDir(); const standaloneDir = path.join(nextDir, NEXTJS_BUILD_STANDALONE_DIR); @@ -165,10 +190,23 @@ export class NextjsBuild extends Construct { return standaloneDir; } - // nextjs project inside of standalone build + // .next/ directory inside of standalone build output directory // contains manifests and server code private _getNextStandaloneBuildDir() { - return path.join(this._getNextStandaloneDir(), this.props.nextjsPath, NEXTJS_BUILD_DIR); + return path.join(this._getNextStandaloneDir(), NEXTJS_BUILD_DIR); // e.g. /home/me/myapp/web/.next/standalone/web/.next + } + + // nextjs project inside of standalone build + // contains manifests and server code + private _getNextStandaloneDir() { + const standaloneDir = this._getStandaloneDir(); + + // if the project is at /home/me/myapp and the nextjs project is at /home/me/myapp/web + // the standalone build of the web app will be at /home/me/myapp/web/.next/standalone/web + // so we need to get the relative path from the standalone dir to the nextjsPath + const relativePath = this._getNextDirRelative(); // e.g. 'web + const standaloneProjectDir = path.join(standaloneDir, relativePath); // e.g. /home/me/myapp/web/.next/standalone/web + return standaloneProjectDir; } // contains static files @@ -206,6 +244,11 @@ export function createArchive({ // get output path const zipFilePath = path.join(zipOutDir, zipFileName); + // delete existing zip file + if (fs.existsSync(zipFilePath)) { + fs.unlinkSync(zipFilePath); + } + // run script to create zipfile, preserving symlinks for node_modules (e.g. pnpm structure) const result = spawn.sync( 'bash', // getting ENOENT when specifying 'node' here for some reason diff --git a/src/NextjsLambda.ts b/src/NextjsLambda.ts index f15d1e6c..9ba32ebd 100644 --- a/src/NextjsLambda.ts +++ b/src/NextjsLambda.ts @@ -50,10 +50,9 @@ export class NextJsLambda extends Construct { constructor(scope: Construct, id: string, props: NextjsLambdaProps) { super(scope, id); const { nextBuild, lambda: functionOptions, isPlaceholder } = props; - // bundle server handler // delete default nextjs handler if it exists - const defaultServerPath = path.join(nextBuild.nextStandaloneDir, props.nextjsPath, 'server.js'); + const defaultServerPath = path.join(nextBuild.nextStandaloneDir, 'server.js'); if (fs.existsSync(defaultServerPath)) { fs.unlinkSync(defaultServerPath); } @@ -61,10 +60,10 @@ export class NextJsLambda extends Construct { // build our server handler in build.nextStandaloneDir const serverHandler = path.resolve(__dirname, '../assets/lambda/NextJsHandler.ts'); // server should live in the same dir as the nextjs app to access deps properly - const serverPath = path.join(props.nextjsPath, 'server.cjs'); + const serverPath = path.join(nextBuild.nextStandaloneDir, 'server.js'); bundleFunction({ inputPath: serverHandler, - outputPath: path.join(nextBuild.nextStandaloneDir, serverPath), + outputPath: serverPath, bundleOptions: { bundle: true, minify: false, @@ -83,7 +82,7 @@ export class NextJsLambda extends Construct { : fs.mkdtempSync(path.join(os.tmpdir(), 'standalone-')) ); const zipFilePath = createArchive({ - directory: nextBuild.nextStandaloneDir, + directory: nextBuild.standaloneDir, zipFileName: 'standalone.zip', zipOutDir, fileGlob: '*', @@ -105,7 +104,7 @@ export class NextJsLambda extends Construct { memorySize: functionOptions?.memorySize || 1024, timeout: functionOptions?.timeout ?? Duration.seconds(10), runtime: LAMBDA_RUNTIME, - handler: path.join(props.nextjsPath, 'server.handler'), + handler: path.join(nextBuild.nextDirRelative, 'server.handler'), code, environment,