Skip to content

Commit

Permalink
fix resolve in image optimization
Browse files Browse the repository at this point in the history
also fix image opt not using streaming
  • Loading branch information
conico974 committed Mar 23, 2024
1 parent 51a2639 commit 059db68
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 49 deletions.
4 changes: 2 additions & 2 deletions packages/open-next/src/adapters/edge-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ const defaultHandler = async (
responseHeaders[key] = value;
}
});
console.log("responseHeaders", responseHeaders);
// console.log("responseHeaders", responseHeaders);
const body = buffer.toString();
console.log("body", body);
// console.log("body", body);

return {
type: "core",
Expand Down
48 changes: 41 additions & 7 deletions packages/open-next/src/adapters/image-optimization-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Writable } from "node:stream";

import { GetObjectCommand, S3Client } from "@aws-sdk/client-s3";
import { loadConfig } from "config/util.js";
import { OpenNextNodeResponse, StreamCreator } from "http/openNextResponse.js";
// @ts-ignore
import { defaultConfig } from "next/dist/server/config-shared";
import {
Expand All @@ -27,8 +28,6 @@ import { setNodeEnv } from "./util.js";
// Expected environment variables
const { BUCKET_NAME, BUCKET_KEY_PREFIX } = process.env;

const s3Client = new S3Client({ logger: awsLogger });

setNodeEnv();
const nextDir = path.join(__dirname, ".next");
const config = loadConfig(nextDir);
Expand Down Expand Up @@ -56,14 +55,15 @@ export const handler = await createGenericHandler({

export async function defaultHandler(
event: InternalEvent,
streamCreator?: StreamCreator,
): Promise<InternalResult> {
// Images are handled via header and query param information.
debug("handler event", event);
const { headers, query: queryString } = event;

try {
// const headers = normalizeHeaderKeysToLowercase(rawHeaders);
ensureBucketExists();

const imageParams = validateImageParams(
headers,
queryString === null ? undefined : queryString,
Expand All @@ -75,9 +75,9 @@ export async function defaultHandler(
downloadHandler,
);

return buildSuccessResponse(result);
return buildSuccessResponse(result, streamCreator);
} catch (e: any) {
return buildFailureResponse(e);
return buildFailureResponse(e, streamCreator);
}
}

Expand Down Expand Up @@ -119,7 +119,23 @@ function validateImageParams(
return imageParams;
}

function buildSuccessResponse(result: any): InternalResult {
function buildSuccessResponse(
result: any,
streamCreator?: StreamCreator,
): InternalResult {
if (streamCreator) {
const response = new OpenNextNodeResponse(
() => void 0,
async () => void 0,
streamCreator,
);
response.writeHead(200, {
Vary: "Accept",
"Cache-Control": `public,max-age=${result.maxAge},immutable`,
"Content-Type": result.contentType,
});
response.end(result.buffer);
}
return {
type: "core",
statusCode: 200,
Expand All @@ -133,8 +149,24 @@ function buildSuccessResponse(result: any): InternalResult {
};
}

function buildFailureResponse(e: any): InternalResult {
function buildFailureResponse(
e: any,
streamCreator?: StreamCreator,
): InternalResult {
debug(e);
if (streamCreator) {
const response = new OpenNextNodeResponse(
() => void 0,
async () => void 0,
streamCreator,
);
response.writeHead(500, {
Vary: "Accept",
"Cache-Control": `public,max-age=60,immutable`,
"Content-Type": "application/json",
});
response.end(e?.message || e?.toString() || e);
}
return {
type: "core",
isBase64Encoded: false,
Expand All @@ -154,10 +186,12 @@ const resolveLoader = () => {
if (typeof openNextParams?.loader === "function") {
return openNextParams.loader();
} else {
const s3Client = new S3Client({ logger: awsLogger });
return Promise.resolve<ImageLoader>({
name: "s3",
// @ts-ignore
load: async (key: string) => {
ensureBucketExists();
const keyPrefix = BUCKET_KEY_PREFIX?.replace(/^\/|\/$/g, "");
const response = await s3Client.send(
new GetObjectCommand({
Expand Down
59 changes: 38 additions & 21 deletions packages/open-next/src/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ export async function build(openNextConfigPath?: string) {
await createCacheAssets(monorepoRoot);

await createServerBundle(config, options);
await createRevalidationBundle();
await createRevalidationBundle(config);
await createImageOptimizationBundle(config);
await createWarmerBundle();
await createWarmerBundle(config);
await generateOutput(options.appPath, options.appBuildOutputPath, config);
logger.info("OpenNext build complete.");
}
Expand Down Expand Up @@ -244,7 +244,7 @@ function initOutputDir() {
fs.writeFileSync(path.join(tempDir, "open-next.config.mjs"), openNextConfig);
}

async function createWarmerBundle() {
async function createWarmerBundle(config: OpenNextConfig) {
logger.info(`Bundling warmer function...`);

const { outputDir } = options;
Expand All @@ -268,8 +268,10 @@ async function createWarmerBundle() {
plugins: [
openNextResolvePlugin({
overrides: {
converter: "dummy",
converter: config.warmer?.override?.converter ?? "dummy",
wrapper: config.warmer?.override?.wrapper,
},
fnName: "warmer",
}),
],
banner: {
Expand All @@ -285,7 +287,7 @@ async function createWarmerBundle() {
);
}

async function createRevalidationBundle() {
async function createRevalidationBundle(config: OpenNextConfig) {
logger.info(`Bundling revalidation function...`);

const { appBuildOutputPath, outputDir } = options;
Expand All @@ -305,8 +307,11 @@ async function createRevalidationBundle() {
outfile: path.join(outputPath, "index.mjs"),
plugins: [
openNextResolvePlugin({
fnName: "revalidate",
overrides: {
converter: "sqs-revalidate",
converter:
config.revalidate?.override?.converter ?? "sqs-revalidate",
wrapper: config.revalidate?.override?.wrapper,
},
}),
],
Expand All @@ -333,20 +338,29 @@ async function createImageOptimizationBundle(config: OpenNextConfig) {
// Copy open-next.config.mjs into the bundle
copyOpenNextConfig(options.tempDir, outputPath);

const plugins =
compareSemver(options.nextVersion, "14.1.1") >= 0
? [
openNextReplacementPlugin({
name: "opennext-14.1.1-image-optimization",
target: /plugins\/image-optimization\/image-optimization\.js/g,
replacements: [
require.resolve(
"./adapters/plugins/image-optimization/image-optimization.replacement.js",
),
],
}),
]
: undefined;
const plugins = [
openNextResolvePlugin({
fnName: "imageOptimization",
overrides: {
converter: config.imageOptimization?.override?.converter,
wrapper: config.imageOptimization?.override?.wrapper,
},
}),
];

if (compareSemver(options.nextVersion, "14.1.1") >= 0) {
plugins.push(
openNextReplacementPlugin({
name: "opennext-14.1.1-image-optimization",
target: /plugins\/image-optimization\/image-optimization\.js/g,
replacements: [
require.resolve(
"./adapters/plugins/image-optimization/image-optimization.replacement.js",
),
],
}),
);
}

// Build Lambda code (1st pass)
// note: bundle in OpenNext package b/c the adapter relies on the
Expand Down Expand Up @@ -639,8 +653,11 @@ async function createCacheAssets(monorepoRoot: string) {
target: ["node18"],
plugins: [
openNextResolvePlugin({
fnName: "initializationFunction",
overrides: {
converter: "dummy",
converter:
config.initializationFunction?.override?.converter ?? "dummy",
wrapper: config.initializationFunction?.override?.wrapper,
},
}),
],
Expand Down
10 changes: 2 additions & 8 deletions packages/open-next/src/build/createServerBundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,14 +213,8 @@ async function generateBundle(
openNextResolvePlugin({
fnName: name,
overrides: {
converter:
typeof overrides.converter === "function"
? "dummy"
: overrides.converter,
wrapper:
typeof overrides.wrapper === "function"
? "aws-lambda"
: overrides.wrapper,
converter: overrides.converter,
wrapper: overrides.wrapper,
},
}),
];
Expand Down
2 changes: 1 addition & 1 deletion packages/open-next/src/core/routing/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export async function handleMiddleware(
const initialUrl = new URL(normalizedPath, host);
initialUrl.search = convertToQueryString(query);
const url = initialUrl.toString();
console.log("url", url, normalizedPath);
// console.log("url", url, normalizedPath);

// @ts-expect-error - This is bundled
const middleware = await import("./middleware.mjs");
Expand Down
26 changes: 16 additions & 10 deletions packages/open-next/src/plugins/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,18 @@ import { readFileSync } from "node:fs";

import { Plugin } from "esbuild";
import type {
IncludedConverter,
DefaultOverrideOptions,
IncludedIncrementalCache,
IncludedQueue,
IncludedTagCache,
IncludedWrapper,
} from "types/open-next";

import logger from "../logger.js";

export interface IPluginSettings {
overrides: {
wrapper?: IncludedWrapper;
converter?: IncludedConverter;
overrides?: {
wrapper?: DefaultOverrideOptions<any, any>["wrapper"];
converter?: DefaultOverrideOptions<any, any>["converter"];
// Right now theses do nothing since there is only one implementation
tag?: IncludedTagCache;
queue?: IncludedQueue;
Expand All @@ -37,17 +36,24 @@ export function openNextResolvePlugin({
logger.debug(`OpenNext Resolve plugin for ${fnName}`);
build.onLoad({ filter: /core\/resolve.js/g }, async (args) => {
let contents = readFileSync(args.path, "utf-8");
if (overrides?.wrapper) {
if (overrides?.wrapper && typeof overrides.wrapper === "string") {
contents = contents.replace(
"../wrappers/aws-lambda.js",
`../wrappers/${overrides.wrapper}.js`,
);
}
if (overrides?.converter) {
contents = contents.replace(
"../converters/aws-apigw-v2.js",
`../converters/${overrides.converter}.js`,
);
if (typeof overrides.converter === "function") {
contents = contents.replace(
"../converters/aws-apigw-v2.js",
`../converters/dummy.js`,
);
} else {
contents = contents.replace(
"../converters/aws-apigw-v2.js",
`../converters/${overrides.converter}.js`,
);
}
}
return {
contents,
Expand Down

0 comments on commit 059db68

Please sign in to comment.