diff --git a/.github/workflows/aws.yml b/.github/workflows/aws.yml index 124dc58..296cdbc 100644 --- a/.github/workflows/aws.yml +++ b/.github/workflows/aws.yml @@ -17,7 +17,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 18.x + node-version: 20.x - name: Install Packages run: npm ci @@ -29,7 +29,7 @@ jobs: run: make chromium.zip - name: Upload Layer Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: chromium path: chromium.zip @@ -45,12 +45,13 @@ jobs: version: - 16 - 18 + - 20 steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.x" @@ -58,7 +59,7 @@ jobs: uses: aws-actions/setup-sam@v2 - name: Download Layer Artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: chromium diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2d78eed..166e1da 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 18.x + node-version: 20.x registry-url: https://registry.npmjs.org/ - run: npm ci diff --git a/Makefile b/Makefile index 9872498..0d7449f 100644 --- a/Makefile +++ b/Makefile @@ -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 test: - sam local invoke --template _/amazon/template.yml --event _/amazon/events/example.com.json node18 - -.fonts.zip: - zip -9 --filesync --move --recurse-paths .fonts.zip .fonts/ + sam local invoke --template _/amazon/template.yml --event _/amazon/events/example.com.json node20 %.zip: npm install --fund=false --package-lock=false npm run build 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 mkdir -p nodejs/node_modules/@sparticuz/chromium/ tar --directory nodejs/node_modules/@sparticuz/chromium/ --extract --file sparticuz-chromium-*.tgz --strip-components=1 diff --git a/_/amazon/events/example.com.json b/_/amazon/events/example.com.json index c60d0e6..a427499 100644 --- a/_/amazon/events/example.com.json +++ b/_/amazon/events/example.com.json @@ -3,21 +3,21 @@ "url": "https://example.com", "expected": { "title": "Example Domain", - "screenshot": "fdd55bf210cb00e00cadf3098055611d11293d02" + "screenshot": "cf91d541795c36da2e8733ed389e9a7951d5fe7f" } }, { "url": "https://example.com", "expected": { "title": "Example Domain", - "screenshot": "fdd55bf210cb00e00cadf3098055611d11293d02" + "screenshot": "cf91d541795c36da2e8733ed389e9a7951d5fe7f" } }, { "url": "https://get.webgl.org", "expected": { "remove": "logo-container", - "screenshot": "7a63a9a18f32dcdad78e1e0a03364fade25c85a8" + "screenshot": "2ca647063ec0be49a6191a7716c6a125e0a5b31b" } } ] diff --git a/_/amazon/handlers/index.js b/_/amazon/handlers/index.js index f41b3dc..a94f091 100644 --- a/_/amazon/handlers/index.js +++ b/_/amazon/handlers/index.js @@ -10,6 +10,7 @@ exports.handler = async (event, context) => { browser = await puppeteer.launch({ args: chromium.args, defaultViewport: chromium.defaultViewport, + dumpio: true, executablePath: await chromium.executablePath(), headless: chromium.headless, ignoreHTTPSErrors: true, diff --git a/_/amazon/template.yml b/_/amazon/template.yml index 046f903..a3fa352 100644 --- a/_/amazon/template.yml +++ b/_/amazon/template.yml @@ -14,6 +14,7 @@ Resources: CompatibleRuntimes: - nodejs16.x - nodejs18.x + - nodejs20.x node16: Type: AWS::Serverless::Function @@ -37,3 +38,14 @@ Resources: - AWSLambdaBasicExecutionRole - AWSXRayDaemonWriteAccess Tracing: Active + node20: + Type: AWS::Serverless::Function + Properties: + Layers: + - !Ref layer + Handler: handlers/index.handler + Runtime: nodejs20.x + Policies: + - AWSLambdaBasicExecutionRole + - AWSXRayDaemonWriteAccess + Tracing: Active diff --git a/bin/al2.tar.br b/bin/al2.tar.br new file mode 100644 index 0000000..50a4e5b Binary files /dev/null and b/bin/al2.tar.br differ diff --git a/bin/al2023.tar.br b/bin/al2023.tar.br new file mode 100644 index 0000000..be16a22 Binary files /dev/null and b/bin/al2023.tar.br differ diff --git a/bin/aws.tar.br b/bin/aws.tar.br deleted file mode 100644 index ab8e70e..0000000 Binary files a/bin/aws.tar.br and /dev/null differ diff --git a/bin/fonts.tar.br b/bin/fonts.tar.br new file mode 100644 index 0000000..92970c3 Binary files /dev/null and b/bin/fonts.tar.br differ diff --git a/package-lock.json b/package-lock.json index 4a313e8..90144e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@sparticuz/chromium", - "version": "119.0.0", + "version": "119.0.1-next.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@sparticuz/chromium", - "version": "119.0.0", + "version": "119.0.1-next.0", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.3", @@ -16,10 +16,10 @@ "@tsconfig/node16": "^16.1.1", "@tsconfig/strictest": "^2.0.2", "@types/follow-redirects": "^1.14.4", - "@types/node": "^18.18.9", + "@types/node": "^18.19.3", "@types/tar-fs": "^2.0.4", "clean-modules": "^3.0.4", - "typescript": "^5.2.2" + "typescript": "^5.3.3" }, "engines": { "node": ">= 16" @@ -47,9 +47,9 @@ } }, "node_modules/@types/node": { - "version": "18.18.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.9.tgz", - "integrity": "sha512-0f5klcuImLnG4Qreu9hPj/rEfFq6YRc5n2mAjSsH+ec/mJL+3voBH0+8T7o8RpFjH7ovc+TRsL/c7OYIQsPTfQ==", + "version": "18.19.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.3.tgz", + "integrity": "sha512-k5fggr14DwAytoA/t8rPrIz++lXK7/DqckthCmoZOKNsEbJkId4Z//BqgApXBUGrGddrigYa1oqheo/7YmW4rg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -268,9 +268,9 @@ "dev": true }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true, "bin": { "tsc": "bin/tsc", diff --git a/package.json b/package.json index 129eae0..863294d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@sparticuz/chromium", - "version": "119.0.0", + "version": "119.0.1-next.0", "description": "Chromium Binary for Serverless Platforms", "keywords": [ "aws", @@ -43,10 +43,10 @@ "@tsconfig/node16": "^16.1.1", "@tsconfig/strictest": "^2.0.2", "@types/follow-redirects": "^1.14.4", - "@types/node": "^18.18.9", + "@types/node": "^18.19.3", "@types/tar-fs": "^2.0.4", "clean-modules": "^3.0.4", - "typescript": "^5.2.2" + "typescript": "^5.3.3" }, "engines": { "node": ">= 16" diff --git a/source/helper.ts b/source/helper.ts index 97cc36d..cc03c92 100644 --- a/source/helper.ts +++ b/source/helper.ts @@ -26,12 +26,29 @@ export const isValidUrl = (input: string) => { export const isRunningInAwsLambda = () => { if ( 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; } else if ( 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; } diff --git a/source/index.ts b/source/index.ts index 79a5e63..522cbbe 100644 --- a/source/index.ts +++ b/source/index.ts @@ -9,7 +9,12 @@ import { https } from "follow-redirects"; import LambdaFS from "./lambdafs"; import { join } from "node:path"; 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 */ interface Viewport { @@ -46,17 +51,36 @@ interface Viewport { if (isRunningInAwsLambda()) { 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) { - process.env["LD_LIBRARY_PATH"] = "/tmp/aws/lib"; + process.env["LD_LIBRARY_PATH"] = "/tmp/al2/lib"; } 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"] = [ ...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(":"), ]), ].join(":"); @@ -300,14 +324,20 @@ class Chromium { } // 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) { // Only inflate graphics stack if needed promises.push(LambdaFS.inflate(`${input}/swiftshader.tar.br`)); } if (isRunningInAwsLambda()) { // 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