Skip to content
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
5 changes: 5 additions & 0 deletions .changeset/chilly-pens-tease.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@opennextjs/aws": patch
---

perf(OriginResolver): cache expensive compute
91 changes: 64 additions & 27 deletions packages/open-next/src/overrides/originResolver/pattern-env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,78 @@ import type { OriginResolver } from "types/overrides";

import { debug, error } from "../../adapters/logger";

// Cache parsed origins and compiled patterns at module level
let cachedOrigins: Record<string, Origin>;
const cachedPatterns: Array<{
key: string;
patterns: string[];
regexes: RegExp[];
}> = [];
let initialized = false;

/**
* Initializes the cached values on the first execution
*/
function initializeOnce(): void {
if (initialized) return;

// Parse origin JSON once
cachedOrigins = JSON.parse(process.env.OPEN_NEXT_ORIGIN ?? "{}") as Record<
string,
Origin
>;

// Pre-compile all regex patterns
const functions = globalThis.openNextConfig.functions ?? {};
for (const key in functions) {
if (key !== "default") {
const value = functions[key];
const regexes: RegExp[] = [];

for (const pattern of value.patterns) {
// Convert cloudfront pattern to regex
const regexPattern = `/${pattern
.replace(/\*\*/g, "(.*)")
.replace(/\*/g, "([^/]*)")
.replace(/\//g, "\\/")
.replace(/\?/g, ".")}`;
regexes.push(new RegExp(regexPattern));
}

cachedPatterns.push({
key,
patterns: value.patterns,
regexes,
});
}
}

initialized = true;
}

const envLoader: OriginResolver = {
name: "env",
resolve: async (_path: string) => {
try {
const origin = JSON.parse(process.env.OPEN_NEXT_ORIGIN ?? "{}") as Record<
string,
Origin
>;
for (const [key, value] of Object.entries(
globalThis.openNextConfig.functions ?? {},
).filter(([key]) => key !== "default")) {
if (
value.patterns.some((pattern) => {
// Convert cloudfront pattern to regex
return new RegExp(
// transform glob pattern to regex
`/${pattern
.replace(/\*\*/g, "(.*)")
.replace(/\*/g, "([^/]*)")
.replace(/\//g, "\\/")
.replace(/\?/g, ".")}`,
).test(_path);
})
) {
debug("Using origin", key, value.patterns);
return origin[key];
initializeOnce();

// Test against pre-compiled patterns
for (const { key, patterns, regexes } of cachedPatterns) {
for (const regex of regexes) {
if (regex.test(_path)) {
debug("Using origin", key, patterns);
return cachedOrigins[key];
}
}
}
if (_path.startsWith("/_next/image") && origin.imageOptimizer) {

if (_path.startsWith("/_next/image") && cachedOrigins.imageOptimizer) {
debug("Using origin", "imageOptimizer", _path);
return origin.imageOptimizer;
return cachedOrigins.imageOptimizer;
}
if (origin.default) {
debug("Using default origin", origin.default, _path);
return origin.default;
if (cachedOrigins.default) {
debug("Using default origin", cachedOrigins.default, _path);
return cachedOrigins.default;
}
return false as const;
} catch (e) {
Expand Down
Loading