Merge pull request #187 from Sparticuz/fix/lambda-node20.x

Node 20 lambda support,
fixes new AL2 lambda libs
This commit is contained in:
Kyle McNally 2023-12-19 10:20:41 -05:00 committed by GitHub
commit 247f748834
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 93 additions and 35 deletions

View File

@ -17,7 +17,7 @@ jobs:
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
node-version: 18.x node-version: 20.x
- name: Install Packages - name: Install Packages
run: npm ci run: npm ci
@ -29,7 +29,7 @@ jobs:
run: make chromium.zip run: make chromium.zip
- name: Upload Layer Artifact - name: Upload Layer Artifact
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
with: with:
name: chromium name: chromium
path: chromium.zip path: chromium.zip
@ -45,12 +45,13 @@ jobs:
version: version:
- 16 - 16
- 18 - 18
- 20
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Setup Python - name: Setup Python
uses: actions/setup-python@v4 uses: actions/setup-python@v5
with: with:
python-version: "3.x" python-version: "3.x"
@ -58,7 +59,7 @@ jobs:
uses: aws-actions/setup-sam@v2 uses: aws-actions/setup-sam@v2
- name: Download Layer Artifact - name: Download Layer Artifact
uses: actions/download-artifact@v3 uses: actions/download-artifact@v4
with: with:
name: chromium name: chromium

View File

@ -18,7 +18,7 @@ jobs:
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
node-version: 18.x node-version: 20.x
registry-url: https://registry.npmjs.org/ registry-url: https://registry.npmjs.org/
- run: npm ci - run: npm ci

View File

@ -8,16 +8,13 @@ pretest:
npm install --prefix _/amazon/handlers puppeteer-core@latest --bin-links=false --fund=false --omit=optional --omit=dev --package-lock=false --save=false npm install --prefix _/amazon/handlers puppeteer-core@latest --bin-links=false --fund=false --omit=optional --omit=dev --package-lock=false --save=false
test: test:
sam local invoke --template _/amazon/template.yml --event _/amazon/events/example.com.json node18 sam local invoke --template _/amazon/template.yml --event _/amazon/events/example.com.json node20
.fonts.zip:
zip -9 --filesync --move --recurse-paths .fonts.zip .fonts/
%.zip: %.zip:
npm install --fund=false --package-lock=false npm install --fund=false --package-lock=false
npm run build npm run build
mkdir -p nodejs mkdir -p nodejs
npm install --prefix nodejs/ tar-fs@2.1.1 follow-redirects@1.15.2 --bin-links=false --fund=false --omit=optional --omit=dev --package-lock=false --save=false npm install --prefix nodejs/ tar-fs@3.0.4 follow-redirects@1.15.3 --bin-links=false --fund=false --omit=optional --omit=dev --package-lock=false --save=false
npm pack npm pack
mkdir -p nodejs/node_modules/@sparticuz/chromium/ mkdir -p nodejs/node_modules/@sparticuz/chromium/
tar --directory nodejs/node_modules/@sparticuz/chromium/ --extract --file sparticuz-chromium-*.tgz --strip-components=1 tar --directory nodejs/node_modules/@sparticuz/chromium/ --extract --file sparticuz-chromium-*.tgz --strip-components=1

View File

@ -3,21 +3,21 @@
"url": "https://example.com", "url": "https://example.com",
"expected": { "expected": {
"title": "Example Domain", "title": "Example Domain",
"screenshot": "fdd55bf210cb00e00cadf3098055611d11293d02" "screenshot": "cf91d541795c36da2e8733ed389e9a7951d5fe7f"
} }
}, },
{ {
"url": "https://example.com", "url": "https://example.com",
"expected": { "expected": {
"title": "Example Domain", "title": "Example Domain",
"screenshot": "fdd55bf210cb00e00cadf3098055611d11293d02" "screenshot": "cf91d541795c36da2e8733ed389e9a7951d5fe7f"
} }
}, },
{ {
"url": "https://get.webgl.org", "url": "https://get.webgl.org",
"expected": { "expected": {
"remove": "logo-container", "remove": "logo-container",
"screenshot": "7a63a9a18f32dcdad78e1e0a03364fade25c85a8" "screenshot": "2ca647063ec0be49a6191a7716c6a125e0a5b31b"
} }
} }
] ]

View File

@ -10,6 +10,7 @@ exports.handler = async (event, context) => {
browser = await puppeteer.launch({ browser = await puppeteer.launch({
args: chromium.args, args: chromium.args,
defaultViewport: chromium.defaultViewport, defaultViewport: chromium.defaultViewport,
dumpio: true,
executablePath: await chromium.executablePath(), executablePath: await chromium.executablePath(),
headless: chromium.headless, headless: chromium.headless,
ignoreHTTPSErrors: true, ignoreHTTPSErrors: true,

View File

@ -14,6 +14,7 @@ Resources:
CompatibleRuntimes: CompatibleRuntimes:
- nodejs16.x - nodejs16.x
- nodejs18.x - nodejs18.x
- nodejs20.x
node16: node16:
Type: AWS::Serverless::Function Type: AWS::Serverless::Function
@ -37,3 +38,14 @@ Resources:
- AWSLambdaBasicExecutionRole - AWSLambdaBasicExecutionRole
- AWSXRayDaemonWriteAccess - AWSXRayDaemonWriteAccess
Tracing: Active Tracing: Active
node20:
Type: AWS::Serverless::Function
Properties:
Layers:
- !Ref layer
Handler: handlers/index.handler
Runtime: nodejs20.x
Policies:
- AWSLambdaBasicExecutionRole
- AWSXRayDaemonWriteAccess
Tracing: Active

BIN
bin/al2.tar.br Normal file

Binary file not shown.

BIN
bin/al2023.tar.br Normal file

Binary file not shown.

Binary file not shown.

BIN
bin/fonts.tar.br Normal file

Binary file not shown.

20
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "@sparticuz/chromium", "name": "@sparticuz/chromium",
"version": "119.0.0", "version": "119.0.1-next.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@sparticuz/chromium", "name": "@sparticuz/chromium",
"version": "119.0.0", "version": "119.0.1-next.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"follow-redirects": "^1.15.3", "follow-redirects": "^1.15.3",
@ -16,10 +16,10 @@
"@tsconfig/node16": "^16.1.1", "@tsconfig/node16": "^16.1.1",
"@tsconfig/strictest": "^2.0.2", "@tsconfig/strictest": "^2.0.2",
"@types/follow-redirects": "^1.14.4", "@types/follow-redirects": "^1.14.4",
"@types/node": "^18.18.9", "@types/node": "^18.19.3",
"@types/tar-fs": "^2.0.4", "@types/tar-fs": "^2.0.4",
"clean-modules": "^3.0.4", "clean-modules": "^3.0.4",
"typescript": "^5.2.2" "typescript": "^5.3.3"
}, },
"engines": { "engines": {
"node": ">= 16" "node": ">= 16"
@ -47,9 +47,9 @@
} }
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "18.18.9", "version": "18.19.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.9.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.3.tgz",
"integrity": "sha512-0f5klcuImLnG4Qreu9hPj/rEfFq6YRc5n2mAjSsH+ec/mJL+3voBH0+8T7o8RpFjH7ovc+TRsL/c7OYIQsPTfQ==", "integrity": "sha512-k5fggr14DwAytoA/t8rPrIz++lXK7/DqckthCmoZOKNsEbJkId4Z//BqgApXBUGrGddrigYa1oqheo/7YmW4rg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"undici-types": "~5.26.4" "undici-types": "~5.26.4"
@ -268,9 +268,9 @@
"dev": true "dev": true
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "5.2.2", "version": "5.3.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
"dev": true, "dev": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",

View File

@ -1,6 +1,6 @@
{ {
"name": "@sparticuz/chromium", "name": "@sparticuz/chromium",
"version": "119.0.0", "version": "119.0.1-next.0",
"description": "Chromium Binary for Serverless Platforms", "description": "Chromium Binary for Serverless Platforms",
"keywords": [ "keywords": [
"aws", "aws",
@ -43,10 +43,10 @@
"@tsconfig/node16": "^16.1.1", "@tsconfig/node16": "^16.1.1",
"@tsconfig/strictest": "^2.0.2", "@tsconfig/strictest": "^2.0.2",
"@types/follow-redirects": "^1.14.4", "@types/follow-redirects": "^1.14.4",
"@types/node": "^18.18.9", "@types/node": "^18.19.3",
"@types/tar-fs": "^2.0.4", "@types/tar-fs": "^2.0.4",
"clean-modules": "^3.0.4", "clean-modules": "^3.0.4",
"typescript": "^5.2.2" "typescript": "^5.3.3"
}, },
"engines": { "engines": {
"node": ">= 16" "node": ">= 16"

View File

@ -26,12 +26,29 @@ export const isValidUrl = (input: string) => {
export const isRunningInAwsLambda = () => { export const isRunningInAwsLambda = () => {
if ( if (
process.env["AWS_EXECUTION_ENV"] && process.env["AWS_EXECUTION_ENV"] &&
/^AWS_Lambda_nodejs/.test(process.env["AWS_EXECUTION_ENV"]) === true process.env["AWS_EXECUTION_ENV"].includes("AWS_Lambda_nodejs") &&
!process.env["AWS_EXECUTION_ENV"].includes("20.x")
) { ) {
return true; return true;
} else if ( } else if (
process.env["AWS_LAMBDA_JS_RUNTIME"] && process.env["AWS_LAMBDA_JS_RUNTIME"] &&
/^nodejs/.test(process.env["AWS_LAMBDA_JS_RUNTIME"]) === true process.env["AWS_LAMBDA_JS_RUNTIME"].includes("nodejs") &&
!process.env["AWS_LAMBDA_JS_RUNTIME"].includes("20.x")
) {
return true;
}
return false;
};
export const isRunningInAwsLambdaNode20 = () => {
if (
process.env["AWS_EXECUTION_ENV"] &&
process.env["AWS_EXECUTION_ENV"].includes("20.x")
) {
return true;
} else if (
process.env["AWS_LAMBDA_JS_RUNTIME"] &&
process.env["AWS_LAMBDA_JS_RUNTIME"].includes("20.x")
) { ) {
return true; return true;
} }

View File

@ -9,7 +9,12 @@ import { https } from "follow-redirects";
import LambdaFS from "./lambdafs"; import LambdaFS from "./lambdafs";
import { join } from "node:path"; import { join } from "node:path";
import { URL } from "node:url"; import { URL } from "node:url";
import { downloadAndExtract, isRunningInAwsLambda, isValidUrl } from "./helper"; import {
downloadAndExtract,
isRunningInAwsLambda,
isValidUrl,
isRunningInAwsLambdaNode20,
} from "./helper";
/** Viewport taken from https://github.com/puppeteer/puppeteer/blob/main/docs/api/puppeteer.viewport.md */ /** Viewport taken from https://github.com/puppeteer/puppeteer/blob/main/docs/api/puppeteer.viewport.md */
interface Viewport { interface Viewport {
@ -46,17 +51,36 @@ interface Viewport {
if (isRunningInAwsLambda()) { if (isRunningInAwsLambda()) {
if (process.env["FONTCONFIG_PATH"] === undefined) { if (process.env["FONTCONFIG_PATH"] === undefined) {
process.env["FONTCONFIG_PATH"] = "/tmp/aws"; process.env["FONTCONFIG_PATH"] = "/tmp/fonts";
} }
if (process.env["LD_LIBRARY_PATH"] === undefined) { if (process.env["LD_LIBRARY_PATH"] === undefined) {
process.env["LD_LIBRARY_PATH"] = "/tmp/aws/lib"; process.env["LD_LIBRARY_PATH"] = "/tmp/al2/lib";
} else if ( } else if (
process.env["LD_LIBRARY_PATH"].startsWith("/tmp/aws/lib") !== true process.env["LD_LIBRARY_PATH"].startsWith("/tmp/al2/lib") !== true
) { ) {
process.env["LD_LIBRARY_PATH"] = [ process.env["LD_LIBRARY_PATH"] = [
...new Set([ ...new Set([
"/tmp/aws/lib", "/tmp/al2/lib",
...process.env["LD_LIBRARY_PATH"].split(":"),
]),
].join(":");
}
}
if (isRunningInAwsLambdaNode20()) {
if (process.env["FONTCONFIG_PATH"] === undefined) {
process.env["FONTCONFIG_PATH"] = "/tmp/fonts";
}
if (process.env["LD_LIBRARY_PATH"] === undefined) {
process.env["LD_LIBRARY_PATH"] = "/tmp/al2023/lib";
} else if (
process.env["LD_LIBRARY_PATH"].startsWith("/tmp/al2023/lib") !== true
) {
process.env["LD_LIBRARY_PATH"] = [
...new Set([
"/tmp/al2023/lib",
...process.env["LD_LIBRARY_PATH"].split(":"), ...process.env["LD_LIBRARY_PATH"].split(":"),
]), ]),
].join(":"); ].join(":");
@ -300,14 +324,20 @@ class Chromium {
} }
// Extract the required files // Extract the required files
const promises = [LambdaFS.inflate(`${input}/chromium.br`)]; const promises = [
LambdaFS.inflate(`${input}/chromium.br`),
LambdaFS.inflate(`${input}/fonts.tar.br`),
];
if (this.graphics) { if (this.graphics) {
// Only inflate graphics stack if needed // Only inflate graphics stack if needed
promises.push(LambdaFS.inflate(`${input}/swiftshader.tar.br`)); promises.push(LambdaFS.inflate(`${input}/swiftshader.tar.br`));
} }
if (isRunningInAwsLambda()) { if (isRunningInAwsLambda()) {
// If running in AWS Lambda, extract more required files // If running in AWS Lambda, extract more required files
promises.push(LambdaFS.inflate(`${input}/aws.tar.br`)); promises.push(LambdaFS.inflate(`${input}/al2.tar.br`));
}
if (isRunningInAwsLambdaNode20()) {
promises.push(LambdaFS.inflate(`${input}/al2023.tar.br`));
} }
// Await all extractions // Await all extractions