sst 2.40.4 → 2.40.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -235,6 +235,7 @@ export declare class NextjsSite extends SsrSite {
235
235
  } | undefined;
236
236
  buildId?: string | undefined;
237
237
  };
238
+ private prefixPattern;
238
239
  private createRevalidationQueue;
239
240
  private createRevalidationTable;
240
241
  getConstructMetadata(): {
@@ -266,6 +267,7 @@ export declare class NextjsSite extends SsrSite {
266
267
  private usePagesManifest;
267
268
  private usePrerenderManifest;
268
269
  private useServerFunctionPerRouteLoggingInjection;
270
+ private useCloudFrontFunctionPrerenderBypassHeaderInjection;
269
271
  private getBuildId;
270
272
  private getSourcemapForAppRoute;
271
273
  private getSourcemapForPagesRoute;
@@ -20,13 +20,14 @@ import { useFunctions } from "./Function.js";
20
20
  import { useDeferredTasks } from "./deferred_task.js";
21
21
  import { Logger } from "../logger.js";
22
22
  const LAYER_VERSION = "2";
23
- const DEFAULT_OPEN_NEXT_VERSION = "2.3.1";
23
+ const DEFAULT_OPEN_NEXT_VERSION = "2.3.5";
24
24
  const DEFAULT_CACHE_POLICY_ALLOWED_HEADERS = [
25
25
  "accept",
26
26
  "rsc",
27
27
  "next-router-prefetch",
28
28
  "next-router-state-tree",
29
29
  "next-url",
30
+ "x-prerender-bypass",
30
31
  ];
31
32
  /**
32
33
  * The `NextjsSite` construct is a higher level CDK construct that makes it easy to create a Next.js app.
@@ -117,7 +118,10 @@ export class NextjsSite extends SsrSite {
117
118
  cloudFrontFunctions: {
118
119
  serverCfFunction: {
119
120
  constructId: "CloudFrontFunction",
120
- injections: [this.useCloudFrontFunctionHostHeaderInjection()],
121
+ injections: [
122
+ this.useCloudFrontFunctionHostHeaderInjection(),
123
+ this.useCloudFrontFunctionPrerenderBypassHeaderInjection(),
124
+ ],
121
125
  },
122
126
  },
123
127
  edgeFunctions: edge
@@ -187,14 +191,14 @@ export class NextjsSite extends SsrSite {
187
191
  },
188
192
  {
189
193
  cacheType: "server",
190
- pattern: "api/*",
194
+ pattern: this.prefixPattern("api/*"),
191
195
  cfFunction: "serverCfFunction",
192
196
  edgeFunction: "edgeServer",
193
197
  origin: "s3",
194
198
  },
195
199
  {
196
200
  cacheType: "server",
197
- pattern: "_next/data/*",
201
+ pattern: this.prefixPattern("_next/data/*"),
198
202
  cfFunction: "serverCfFunction",
199
203
  edgeFunction: "edgeServer",
200
204
  origin: "s3",
@@ -208,31 +212,31 @@ export class NextjsSite extends SsrSite {
208
212
  },
209
213
  {
210
214
  cacheType: "server",
211
- pattern: "api/*",
215
+ pattern: this.prefixPattern("api/*"),
212
216
  cfFunction: "serverCfFunction",
213
217
  origin: "regionalServer",
214
218
  },
215
219
  {
216
220
  cacheType: "server",
217
- pattern: "_next/data/*",
221
+ pattern: this.prefixPattern("_next/data/*"),
218
222
  cfFunction: "serverCfFunction",
219
223
  origin: "regionalServer",
220
224
  },
221
225
  ]),
222
226
  {
223
227
  cacheType: "server",
224
- pattern: "_next/image*",
228
+ pattern: this.prefixPattern("_next/image*"),
225
229
  cfFunction: "serverCfFunction",
226
230
  origin: "imageOptimizer",
227
231
  },
228
232
  // create 1 behaviour for each top level asset file/folder
229
233
  ...fs.readdirSync(path.join(sitePath, ".open-next/assets")).map((item) => ({
230
234
  cacheType: "static",
231
- pattern: fs
235
+ pattern: this.prefixPattern(fs
232
236
  .statSync(path.join(sitePath, ".open-next/assets", item))
233
237
  .isDirectory()
234
238
  ? `${item}/*`
235
- : item,
239
+ : item),
236
240
  origin: "s3",
237
241
  })),
238
242
  ],
@@ -242,6 +246,13 @@ export class NextjsSite extends SsrSite {
242
246
  buildId: this.getBuildId(),
243
247
  });
244
248
  }
249
+ prefixPattern(pattern) {
250
+ // Prefix CloudFront distribution behavior path patterns with `basePath` if configured
251
+ const { basePath } = this.useRoutesManifest();
252
+ return basePath && basePath.length > 0
253
+ ? `${basePath.slice(1)}/${pattern}`
254
+ : pattern;
255
+ }
245
256
  createRevalidationQueue() {
246
257
  if (!this.serverFunction)
247
258
  return;
@@ -520,6 +531,15 @@ if (event.rawPath) {
520
531
  },
521
532
  }));
522
533
  }
534
+ }`;
535
+ }
536
+ useCloudFrontFunctionPrerenderBypassHeaderInjection() {
537
+ // In Next.js page router preview mode (depends on the cookie __prerender_bypass),
538
+ // to ensure we receive the cached page instead of the preview version, we set the
539
+ // header "x-prerender-bypass", and add it to cache policy's allowed headers.
540
+ return `
541
+ if (request.cookies["__prerender_bypass"]) {
542
+ request.headers["x-prerender-bypass"] = { value: "true" };
523
543
  }`;
524
544
  }
525
545
  getBuildId() {
@@ -58,7 +58,7 @@ export declare class RemixSite extends SsrSite {
58
58
  from: string;
59
59
  to: string;
60
60
  cached: true;
61
- versionedSubDir: string;
61
+ versionedSubDir: string | undefined;
62
62
  }[];
63
63
  };
64
64
  regionalServer?: {
@@ -91,7 +91,8 @@ export declare class RemixSite extends SsrSite {
91
91
  } | undefined;
92
92
  buildId?: string | undefined;
93
93
  };
94
- protected getServerModuleFormat(): "cjs" | "esm";
94
+ private hasViteConfig;
95
+ private getServerModuleFormat;
95
96
  private createServerLambdaBundle;
96
97
  getConstructMetadata(): {
97
98
  data: {
@@ -26,8 +26,9 @@ export class RemixSite extends SsrSite {
26
26
  }
27
27
  plan() {
28
28
  const { path: sitePath, edge } = this.props;
29
- const { handler, inject } = this.createServerLambdaBundle(edge ? "edge-server.js" : "regional-server.js");
30
- const format = this.getServerModuleFormat();
29
+ const isUsingVite = this.hasViteConfig();
30
+ const format = this.getServerModuleFormat(isUsingVite);
31
+ const { handler, inject } = this.createServerLambdaBundle(isUsingVite, edge ? "edge-server.js" : "regional-server.js");
31
32
  const serverConfig = {
32
33
  description: "Server handler for Remix",
33
34
  handler,
@@ -38,6 +39,11 @@ export class RemixSite extends SsrSite {
38
39
  },
39
40
  },
40
41
  };
42
+ // The path for all files that need to be in the "/" directory (static assets)
43
+ // is different when using Vite. These will be located in the "build/client"
44
+ // path of the output. It will be the "public" folder when using remix config.
45
+ const assetsPath = isUsingVite ? path.join("build", "client") : "public";
46
+ const assetsVersionedSubDir = isUsingVite ? undefined : "build";
41
47
  return this.validatePlan({
42
48
  edge: edge ?? false,
43
49
  cloudFrontFunctions: {
@@ -79,10 +85,10 @@ export class RemixSite extends SsrSite {
79
85
  type: "s3",
80
86
  copy: [
81
87
  {
82
- from: "public",
88
+ from: assetsPath,
83
89
  to: "",
84
90
  cached: true,
85
- versionedSubDir: "build",
91
+ versionedSubDir: assetsVersionedSubDir,
86
92
  },
87
93
  ],
88
94
  },
@@ -101,10 +107,10 @@ export class RemixSite extends SsrSite {
101
107
  origin: "regionalServer",
102
108
  },
103
109
  // create 1 behaviour for each top level asset file/folder
104
- ...fs.readdirSync(path.join(sitePath, "public")).map((item) => ({
110
+ ...fs.readdirSync(path.join(sitePath, assetsPath)).map((item) => ({
105
111
  cacheType: "static",
106
112
  pattern: fs
107
- .statSync(path.join(sitePath, "public", item))
113
+ .statSync(path.join(sitePath, assetsPath, item))
108
114
  .isDirectory()
109
115
  ? `${item}/*`
110
116
  : item,
@@ -114,8 +120,17 @@ export class RemixSite extends SsrSite {
114
120
  ],
115
121
  });
116
122
  }
117
- getServerModuleFormat() {
123
+ hasViteConfig() {
118
124
  const { path: sitePath } = this.props;
125
+ return (fs.existsSync(path.resolve(sitePath, "vite.config.ts")) ||
126
+ fs.existsSync(path.resolve(sitePath, "vite.config.js")));
127
+ }
128
+ getServerModuleFormat(isUsingVite) {
129
+ const { path: sitePath } = this.props;
130
+ // Remix has two possible config formats: "remix.config.js" or "vite.config.ts/js".
131
+ // If using the vite format, we can short circuit the logic and just return ESM.
132
+ if (isUsingVite)
133
+ return "esm";
119
134
  // Validate config path
120
135
  const configPath = path.resolve(sitePath, "remix.config.js");
121
136
  if (!fs.existsSync(configPath)) {
@@ -158,7 +173,7 @@ export class RemixSite extends SsrSite {
158
173
  });
159
174
  return format;
160
175
  }
161
- createServerLambdaBundle(wrapperFile) {
176
+ createServerLambdaBundle(isUsingVite, wrapperFile) {
162
177
  // Create a Lambda@Edge handler for the Remix server bundle.
163
178
  //
164
179
  // Note: Remix does perform their own internal ESBuild process, but it
@@ -178,13 +193,24 @@ export class RemixSite extends SsrSite {
178
193
  // Ensure build directory exists
179
194
  const buildPath = path.join(this.props.path, "build");
180
195
  fs.mkdirSync(buildPath, { recursive: true });
181
- // Copy the server lambda handler
182
- fs.copyFileSync(path.resolve(__dirname, `../support/remix-site-function/${wrapperFile}`), path.join(buildPath, "server.js"));
196
+ // Copy the server lambda handler and pre-append the build injection based
197
+ // on the config file used.
198
+ const content = [
199
+ // When using Vite config, the output build will be "server/index.js"
200
+ // and when using Remix config it will be `server.js`.
201
+ `// Import the server build that was produced by 'remix build'`,
202
+ isUsingVite
203
+ ? `import * as remixServerBuild from "./server/index.js";`
204
+ : `import * as remixServerBuild from "./index.js";`,
205
+ ``,
206
+ fs.readFileSync(path.resolve(__dirname, `../support/remix-site-function/${wrapperFile}`), { encoding: "utf8" }),
207
+ ].join("\n");
208
+ fs.writeFileSync(path.resolve(buildPath, "server.js"), content);
183
209
  // Copy the Remix polyfil to the server build directory
184
210
  //
185
211
  // Note: We need to ensure that the polyfills are injected above other code that
186
- // will depend on them. Importing them within the top of the lambda code
187
- // doesn't appear to guarantee this, we therefore leverage ESBUild's
212
+ // will depend on them when not using Vite. Importing them within the top of the
213
+ // lambda code doesn't appear to guarantee this, we therefore leverage ESBUild's
188
214
  // `inject` option to ensure that the polyfills are injected at the top of
189
215
  // the bundle.
190
216
  const polyfillDest = path.join(buildPath, "polyfill.js");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "sideEffects": false,
3
3
  "name": "sst",
4
- "version": "2.40.4",
4
+ "version": "2.40.5",
5
5
  "bin": {
6
6
  "sst": "cli/sst.js"
7
7
  },
@@ -118,7 +118,7 @@
118
118
  "@types/ws": "^8.5.3",
119
119
  "@types/yargs": "^17.0.13",
120
120
  "archiver": "^5.3.1",
121
- "astro-sst": "2.40.4",
121
+ "astro-sst": "2.40.5",
122
122
  "async": "^3.2.4",
123
123
  "tsx": "^3.12.1",
124
124
  "typescript": "^5.2.2",
@@ -1,20 +1,12 @@
1
1
  // This is a custom Lambda@Edge handler which imports the Remix server
2
2
  // build and performs the Remix server rendering.
3
3
 
4
- // We have to ensure that our polyfills are imported prior to any other modules
5
- // which may depend on them;
6
- import { installGlobals } from "@remix-run/node";
7
- installGlobals();
8
-
9
4
  import {
10
5
  createRequestHandler as createNodeRequestHandler,
11
6
  readableStreamToString,
12
7
  } from "@remix-run/node";
13
8
  import { URL } from "url";
14
9
 
15
- // Import the server build that was produced by `remix build`;
16
- import * as remixServerBuild from "./index.js";
17
-
18
10
  /**
19
11
  * Common binary MIME types
20
12
  */
@@ -1,19 +1,11 @@
1
1
  // This is a custom Lambda URL handler which imports the Remix server
2
2
  // build and performs the Remix server rendering.
3
3
 
4
- // We have to ensure that our polyfills are imported prior to any other modules
5
- // which may depend on them;
6
- import { installGlobals } from "@remix-run/node";
7
- installGlobals();
8
-
9
4
  import {
10
5
  createRequestHandler as createNodeRequestHandler,
11
6
  readableStreamToString,
12
7
  } from "@remix-run/node";
13
8
 
14
- // Import the server build that was produced by `remix build`;
15
- import * as remixServerBuild from "./index.js";
16
-
17
9
  /**
18
10
  * Common binary MIME types
19
11
  */