build sharp for specific platform with esbuild and deploy it with NodejsFunction lambda
Asked Answered
G

1

7

I'm trying to deploy a Lambda function which uses sharp for image processing. I do not want to use docker builds -- I have to use esbuild. Here is my lambda definition in cdk:

  const processUploadedImageLambdaFunction = new NodejsFunction(
      this,
      `${deployEnv()}_processUploadedImage`,
      {
        runtime: lambda.Runtime.NODEJS_18_X,
        // handler: "index.handler",
        entry: `${__dirname}/../lambda-fns/lambdas/processUploadedImage/index.ts`,
        bundling: {
          target: "node18",
          sourceMap: true,
          sourceMapMode: SourceMapMode.INLINE,
          sourcesContent: false,
          externalModules: ["sharp"],
          nodeModules: ["sharp"],
          command: ["npm rebuild sharp --arch=x64 --platform=linux sharp"],
        },

        insightsVersion,
        logRetention,
        // memorySize: 10240,
        memorySize: 3008,
        timeout: cdk.Duration.seconds(30),
        environment: {
          ...config,
        },
      },
    )

When the function runs getting following exception:

{
    "errorType": "Error",
    "errorMessage": "\nSomething went wrong installing the \"sharp\" module\n\nCannot find module '../build/Release/sharp-linux-x64.node'\nRequire stack:\n- /var/task/node_modules/sharp/lib/sharp.js\n- /var/task/node_modules/sharp/lib/constructor.js\n- /var/task/node_modules/sharp/lib/index.js\n- /var/task/index.js\n- /var/runtime/index.mjs\n\nPossible solutions:\n- Install with the --verbose flag and look for errors: \"npm install --ignore-scripts=false --verbose sharp\"\n- Install for the current linux-x64 runtime: \"npm install --platform=linux --arch=x64 sharp\"\n- Consult the installation documentation: https://sharp.pixelplumbing.com/install",
    "stack": [
        "Error: ",
        "Something went wrong installing the \"sharp\" module",
        "",
        "Cannot find module '../build/Release/sharp-linux-x64.node'",
        "Require stack:",
        "- /var/task/node_modules/sharp/lib/sharp.js",
        "- /var/task/node_modules/sharp/lib/constructor.js",
        "- /var/task/node_modules/sharp/lib/index.js",
        "- /var/task/index.js",
        "- /var/runtime/index.mjs",
        "",
        "Possible solutions:",
        "- Install with the --verbose flag and look for errors: \"npm install --ignore-scripts=false --verbose sharp\"",
        "- Install for the current linux-x64 runtime: \"npm install --platform=linux --arch=x64 sharp\"",
        "- Consult the installation documentation: https://sharp.pixelplumbing.com/install",
        "    at Object.<anonymous> (/var/task/node_modules/sharp/lib/sharp.js:31:9)",
        "    at Module._compile (node:internal/modules/cjs/loader:1254:14)",
        "    at Module._extensions..js (node:internal/modules/cjs/loader:1308:10)",
        "    at Module.load (node:internal/modules/cjs/loader:1117:32)",
        "    at Module._load (node:internal/modules/cjs/loader:958:12)",
        "    at Module.require (node:internal/modules/cjs/loader:1141:19)",
        "    at require (node:internal/modules/cjs/helpers:110:18)",
        "    at Object.<anonymous> (/var/task/node_modules/sharp/lib/constructor.js:8:1)",
        "    at Module._compile (node:internal/modules/cjs/loader:1254:14)",
        "    at Module._extensions..js (node:internal/modules/cjs/loader:1308:10)"
    ]
}

What am I missing? How do I build sharp for specific platform with esbuild and deploy it with NodejsFunction lambda? Is there a way to do it with bare bones esbuild and avoid using more advanced techniques like docker and layers?

Gretchen answered 27/5, 2023 at 16:44 Comment(0)
P
3

Update: Seems not to work out of the box with sharp >= v0.33. Consider using a lambda layer for sharp or follow the sharp documentation for AWS Lambda.


I can successfully use sharp in a lambda NodeJS CDK function using esbuild bundling (not docker bundling & no lambda layer) with the following options. Also works in a Github Action workflow.

(Note: Use --arch=arm64 for CDK lambda.Architecture.ARM_64)

new NodejsFunction(this, "SOME_ID", {
  // ...
  bundling: {
    externalModules: ["sharp"],
    nodeModules: ["sharp"],
    commandHooks: {
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      beforeBundling(inputDir: string, outputDir: string): string[] {
        return [];
      },
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      beforeInstall(inputDir: string, outputDir: string): string[] {
        return [];
      },
      afterBundling(inputDir: string, outputDir: string): string[] {
        return [`cd ${outputDir}`, "rm -rf node_modules/sharp && npm install --no-save --arch=x86 --platform=linux sharp"];
      }
    }
  }
  // ...
});

Found this solution via aws-solutions/serverless-image-handler

Plautus answered 11/10, 2023 at 10:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.