Compare commits
262 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
cd113882ea | |
|
|
f664837067 | |
|
|
1dbbfc7ac4 | |
|
|
dfd47f4102 | |
|
|
540387d11a | |
|
|
a64b8612f6 | |
|
|
c031905fbf | |
|
|
517b6c43a4 | |
|
|
f9f32ca64c | |
|
|
2f7267da42 | |
|
|
b580ec7aae | |
|
|
58613272ad | |
|
|
8028819dfe | |
|
|
995bc5a604 | |
|
|
c51ae58407 | |
|
|
2c715c4e97 | |
|
|
2bcd54a6c8 | |
|
|
bd9c5e9014 | |
|
|
3e6aa79fb8 | |
|
|
d0543e6139 | |
|
|
41223a10e9 | |
|
|
e4de013045 | |
|
|
4ce60bdd4d | |
|
|
0f12e5f2d7 | |
|
|
94b8687686 | |
|
|
bb952358a2 | |
|
|
2c5dabf81b | |
|
|
c0b12ce7be | |
|
|
ce553320d8 | |
|
|
c640690f16 | |
|
|
8efe5f9145 | |
|
|
aaa9fa63d0 | |
|
|
800c97f871 | |
|
|
1da7ed4b19 | |
|
|
918c7ffe9e | |
|
|
01c4850279 | |
|
|
9a6247d0e3 | |
|
|
da5037292d | |
|
|
8206092f26 | |
|
|
81f83bbd65 | |
|
|
986fca4ff3 | |
|
|
6e07eb0d63 | |
|
|
857ae08500 | |
|
|
424f3e9058 | |
|
|
85db6ca4e2 | |
|
|
0f93a89596 | |
|
|
68f6d4858f | |
|
|
590f35ee6e | |
|
|
24fa1a2210 | |
|
|
30743fd482 | |
|
|
29004cbb13 | |
|
|
b5766d628b | |
|
|
031b2d8bc4 | |
|
|
247f748834 | |
|
|
849e769e78 | |
|
|
a93aa49c50 | |
|
|
05d4445708 | |
|
|
2f52e9a534 | |
|
|
7cfd79de38 | |
|
|
e5334713e3 | |
|
|
6dba931a9a | |
|
|
80cf8e79ce | |
|
|
62b5d05260 | |
|
|
5597e45f59 | |
|
|
2b5ff55015 | |
|
|
f52f2c825c | |
|
|
3f02dfe58e | |
|
|
cdf28b5a76 | |
|
|
49c1b7671c | |
|
|
ec5856facc | |
|
|
2578196d06 | |
|
|
dc23b5d6ed | |
|
|
fc6b69d653 | |
|
|
c683d75545 | |
|
|
6fe1820833 | |
|
|
1b84efe984 | |
|
|
28b086cee9 | |
|
|
b6817b6bac | |
|
|
b8a1c5f2c0 | |
|
|
d63a8efc0d | |
|
|
ad676965b2 | |
|
|
438c79c490 | |
|
|
46b552d4a3 | |
|
|
057856d4af | |
|
|
4f485287b4 | |
|
|
8fdbb07701 | |
|
|
4f8549ce5b | |
|
|
1c43eae4d7 | |
|
|
bcdd0e5ad0 | |
|
|
e77f679a6b | |
|
|
8a39891caa | |
|
|
339cbe0e19 | |
|
|
18c8adb646 | |
|
|
b91a150173 | |
|
|
693a7f4abd | |
|
|
3a22d405ce | |
|
|
9b25726538 | |
|
|
edd4995bdf | |
|
|
cf7443fedc | |
|
|
0e04dd710c | |
|
|
8b63fb075d | |
|
|
6d190e5ebb | |
|
|
29c2468ccf | |
|
|
506d4c2cd7 | |
|
|
a6e6e8dfad | |
|
|
5042a820c1 | |
|
|
161d9efbf5 | |
|
|
67e1c394a5 | |
|
|
1c2e225f14 | |
|
|
93954a5217 | |
|
|
60971353a8 | |
|
|
8ec8c6edbe | |
|
|
a3999e7b35 | |
|
|
27ba2eeaf9 | |
|
|
11d63b6be6 | |
|
|
9626bb09d9 | |
|
|
6fc18b6935 | |
|
|
aeee592507 | |
|
|
9f0ae64364 | |
|
|
2f57d09fe6 | |
|
|
74283507ac | |
|
|
657597064f | |
|
|
07b12068f8 | |
|
|
b8a406a793 | |
|
|
b21fdacfc3 | |
|
|
3b51330eeb | |
|
|
7c333430bd | |
|
|
b1810b4165 | |
|
|
2c2eebac1f | |
|
|
ccf85f2fdb | |
|
|
c72041fcd0 | |
|
|
71b254abe4 | |
|
|
0786301a85 | |
|
|
ffc8ec4c1d | |
|
|
96f0556ba3 | |
|
|
1b7fc2fae9 | |
|
|
5cbee63a08 | |
|
|
773a268a66 | |
|
|
2182f18937 | |
|
|
98938c1ff4 | |
|
|
9d49cf74d9 | |
|
|
4c7f43d497 | |
|
|
6b87b60d1a | |
|
|
dfdd205528 | |
|
|
852a34f88b | |
|
|
8ab732f14e | |
|
|
f337cdad26 | |
|
|
503db13867 | |
|
|
a7320dd0e2 | |
|
|
325fcdc21f | |
|
|
a5905cc5bc | |
|
|
d4d290ac54 | |
|
|
665283328a | |
|
|
47dc5aef53 | |
|
|
3f6eb9ee91 | |
|
|
0c1351f01b | |
|
|
b57702b414 | |
|
|
38e10469c5 | |
|
|
e0a6b12631 | |
|
|
e5bd99a1f9 | |
|
|
1889639200 | |
|
|
456b5d58e3 | |
|
|
6eb3149980 | |
|
|
3b2668d465 | |
|
|
0d77a3c6ed | |
|
|
f26740b0ea | |
|
|
3ab680c5e4 | |
|
|
30933b91b1 | |
|
|
fe8e52d89d | |
|
|
6352e67925 | |
|
|
e147b8ea40 | |
|
|
0335251da0 | |
|
|
efecce8736 | |
|
|
6e12eeb52e | |
|
|
47fcf6ccfc | |
|
|
f82321a695 | |
|
|
1631926197 | |
|
|
2192fedc04 | |
|
|
48f29e0403 | |
|
|
d9ab0d2058 | |
|
|
3aca06d426 | |
|
|
9e148b56f3 | |
|
|
8c2a664099 | |
|
|
0b03ea9de2 | |
|
|
0f1d01e4c8 | |
|
|
d8acc9c8d5 | |
|
|
b077bd9340 | |
|
|
509470c5cb | |
|
|
48b9273bfb | |
|
|
16b3817e52 | |
|
|
fcfc6b72d8 | |
|
|
58460d821c | |
|
|
3737536c95 | |
|
|
dcec05abfc | |
|
|
b8bfaffda1 | |
|
|
dc0a61daa1 | |
|
|
f9d6faebe1 | |
|
|
ba2b8b694f | |
|
|
c7284f47ea | |
|
|
58bf66e575 | |
|
|
29ee254e56 | |
|
|
bb9b97fb74 | |
|
|
5424a18a82 | |
|
|
ee4c497e64 | |
|
|
a4d7b52dce | |
|
|
0270285a4a | |
|
|
12764483af | |
|
|
4f4a2159ea | |
|
|
94f9f9b59a | |
|
|
52a16b8d7d | |
|
|
7bd39feec3 | |
|
|
c42af097d4 | |
|
|
639b156f72 | |
|
|
40428cc139 | |
|
|
640fcc3be1 | |
|
|
65afc2c0c9 | |
|
|
f4e3518619 | |
|
|
4fb4a6f17d | |
|
|
10d3f8b9eb | |
|
|
71d4abf4a3 | |
|
|
1a1d068697 | |
|
|
0a26693b5f | |
|
|
24ff717fe7 | |
|
|
4d8feb364d | |
|
|
62bc5aea17 | |
|
|
e79d99d8ff | |
|
|
1c72dc036c | |
|
|
083fd747ff | |
|
|
9e34256b2f | |
|
|
3deea91193 | |
|
|
b286dc3fc2 | |
|
|
03ec742402 | |
|
|
9578aa0154 | |
|
|
1ef67ceae8 | |
|
|
0bc1e5d1ba | |
|
|
60245f16bf | |
|
|
0562aca09f | |
|
|
4cda3ab393 | |
|
|
db8a2f8187 | |
|
|
5d81cf2367 | |
|
|
8a57bf8e0b | |
|
|
f4125e2770 | |
|
|
7822c9b4c8 | |
|
|
dde6fd07cd | |
|
|
5e9be990f8 | |
|
|
50af06897a | |
|
|
c092f60c12 | |
|
|
fa6e3ac2a7 | |
|
|
16b09ba518 | |
|
|
1483601cdd | |
|
|
e0b050dacf | |
|
|
f599eeede1 | |
|
|
623accd814 | |
|
|
f8e6d26afd | |
|
|
eeef9b1c18 | |
|
|
82a8342ecd | |
|
|
7b58b551cf | |
|
|
cb404f1ed4 | |
|
|
ce3ca54bb2 | |
|
|
4d93e19f31 | |
|
|
cdf799ca62 | |
|
|
a3ac8c640b |
|
|
@ -1 +1 @@
|
|||
github:Sparticuz
|
||||
github: Sparticuz
|
||||
|
|
|
|||
|
|
@ -7,15 +7,16 @@ labels: bug
|
|||
|
||||
<!---
|
||||
For Chromium-specific bugs, please refer to: https://bugs.chromium.org/p/chromium
|
||||
For Puppeteer-specific bugs, please refer to: https://github.com/GoogleChrome/puppeteer/issues
|
||||
For Puppeteer-specific bugs, please refer to: https://github.com/puppeteer/puppeteer/issues
|
||||
For Playwright-specific bugs, please refer to: https://github.com/microsoft/playwright/issues
|
||||
-->
|
||||
|
||||
## Environment
|
||||
* `chrome-aws-lambda` Version:
|
||||
* `puppeteer` / `puppeteer-core` Version:
|
||||
* OS: <!-- Linux | Mac | Windows -->
|
||||
* Node.js Version: <!-- 8.x | 10.x | 12.x | 14.x -->
|
||||
* Lambda / GCF Runtime: <!-- `nodejs8.10` | `nodejs10.x` | `nodejs12.x` -->
|
||||
|
||||
- `chromium` Version:
|
||||
- `puppeteer` / `puppeteer-core` Version:
|
||||
- Node.js Version: <!-- 16.x | 18.x -->
|
||||
- Lambda / GCF Runtime: <!-- `nodejs16` | `nodejs18.x` -->
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
|
|
@ -31,17 +32,17 @@ For Puppeteer-specific bugs, please refer to: https://github.com/GoogleChrome/pu
|
|||
|
||||
<!--
|
||||
```js
|
||||
const chromium = require('chrome-aws-lambda');
|
||||
const chromium = require('chromium');
|
||||
|
||||
exports.handler = async (event, context, callback) => {
|
||||
let result = null;
|
||||
let browser = null;
|
||||
|
||||
try {
|
||||
browser = await chromium.puppeteer.launch({
|
||||
browser = await puppeteer.launch({
|
||||
args: chromium.args,
|
||||
defaultViewport: chromium.defaultViewport,
|
||||
executablePath: await chromium.executablePath,
|
||||
executablePath: await chromium.executablePath(),
|
||||
headless: chromium.headless,
|
||||
ignoreHTTPSErrors: true,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: /
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: /
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
|
@ -2,9 +2,9 @@ name: AWS Lambda CI
|
|||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
@ -12,21 +12,24 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16.x
|
||||
node-version: 20.x
|
||||
|
||||
- name: Install Packages
|
||||
run: npm install
|
||||
run: npm ci
|
||||
|
||||
- name: Compile Typescript
|
||||
run: npm run build
|
||||
|
||||
- name: Create Lambda Layer
|
||||
run: make chromium.zip
|
||||
|
||||
- name: Upload Layer Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: chromium
|
||||
path: chromium.zip
|
||||
|
|
@ -40,22 +43,23 @@ jobs:
|
|||
event:
|
||||
- example.com
|
||||
version:
|
||||
- 14
|
||||
- 16
|
||||
- 18
|
||||
- 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v3
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
python-version: "3.x"
|
||||
|
||||
- name: Setup AWS SAM CLI
|
||||
uses: aws-actions/setup-sam@v2
|
||||
|
||||
- name: Download Layer Artifact
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: chromium
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "*"
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Build and release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Install jq so I can edit package.json from the command line
|
||||
- run: sudo apt-get install jq -y
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20.x
|
||||
registry-url: https://registry.npmjs.org/
|
||||
|
||||
- run: npm ci
|
||||
|
||||
- run: npm run build
|
||||
|
||||
- name: Release chromium on npmjs
|
||||
run: npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
|
||||
|
||||
- name: Create Lambda Layer
|
||||
run: make chromium-${{ github.ref_name }}-layer.zip
|
||||
|
||||
# Change the package name to chromium-min,
|
||||
# delete the bin folder from the files array
|
||||
# so that it doesn't publish the binaries to -min
|
||||
- name: Cleanup and prepare for chromium-min
|
||||
run: |
|
||||
jq '.name="@sparticuz/chromium-min"' package.json > .package.json
|
||||
jq 'del(.files[] | select(. == "bin"))' .package.json > package.json
|
||||
jq '.homepage="https://github.com/Sparticuz/chromium#-min-package"' package.json > .package.json
|
||||
mv .package.json package.json
|
||||
rm package-lock.json
|
||||
npm install
|
||||
|
||||
- name: Release chromium-min on npmjs
|
||||
run: npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
|
||||
|
||||
- name: Create Chromium Pack
|
||||
run: |
|
||||
cd bin
|
||||
tar -cvf chromium-${{ github.ref_name }}-pack.tar *
|
||||
mv chromium-${{ github.ref_name }}-pack.tar ..
|
||||
cd ..
|
||||
|
||||
- name: Upload items to Github Release
|
||||
uses: ncipollo/release-action@v1.14.0
|
||||
with:
|
||||
tag: ${{ github.ref_name }}
|
||||
body: |
|
||||
# [@sparticuz/chromium ${{ github.ref_name }}](https://www.npmjs.com/package/@sparticuz/chromium), [@sparticuz/chromium-min ${{ github.ref_name }}](https://www.npmjs.com/package/@sparticuz/chromium-min)
|
||||
The `chromium-${{ github.ref_name }}-layer.zip` file may be uploaded directly as a layer in AWS Lambda using the following code
|
||||
```
|
||||
bucketName="chromiumUploadBucket" && \
|
||||
aws s3 cp chromium-${{ github.ref_name }}-layer.zip "s3://${bucketName}/chromiumLayers/chromium-${{ github.ref_name }}-layer.zip" && \
|
||||
aws lambda publish-layer-version --layer-name chromium --description "Chromium ${{ github.ref_name }}" --content "S3Bucket=${bucketName},S3Key=chromiumLayers/chromium-${{ github.ref_name }}-layer.zip" --compatible-runtimes nodejs --compatible-architectures x86_64
|
||||
```
|
||||
The `chromium-${{ github.ref_name }}-pack.tar` file may be uploaded to any https endpoint and the remote location may be used as the `input` variable in the `chromium.executablePath(input)` function.
|
||||
artifacts: "chromium-${{ github.ref_name }}-layer.zip,chromium-${{ github.ref_name }}-pack.tar"
|
||||
prerelease: false
|
||||
draft: true
|
||||
generateReleaseNotes: true
|
||||
token: ${{ github.token }}
|
||||
owner: Sparticuz
|
||||
repo: chromium
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
.fonts
|
||||
*.log
|
||||
*.pem
|
||||
*.pem.pub
|
||||
*.zip
|
||||
|
|
@ -7,6 +6,10 @@ bin/chromium-*.br
|
|||
build
|
||||
node_modules
|
||||
nodejs
|
||||
package-lock.json
|
||||
_/amazon/samconfig.toml
|
||||
_/amazon/.aws-sam
|
||||
*.tar
|
||||
*.tgz
|
||||
examples/**/package-lock.json
|
||||
examples/**/.serverless
|
||||
docker
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
_
|
||||
.fonts
|
||||
*.zip
|
||||
12
Makefile
12
Makefile
|
|
@ -8,19 +8,23 @@ 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 node20
|
||||
|
||||
test16:
|
||||
sam local invoke --template _/amazon/template.yml --event _/amazon/events/example.com.json node16
|
||||
|
||||
.fonts.zip:
|
||||
zip -9 --filesync --move --recurse-paths .fonts.zip .fonts/
|
||||
test18:
|
||||
sam local invoke --template _/amazon/template.yml --event _/amazon/events/example.com.json node18
|
||||
|
||||
%.zip:
|
||||
npm install --fund=false --package-lock=false
|
||||
npm run build
|
||||
mkdir -p nodejs
|
||||
npm install --prefix nodejs/ tar-fs@2.1.1 --bin-links=false --fund=false --omit=optional --omit=dev --package-lock=false --save=false
|
||||
npm install --prefix nodejs/ tar-fs@3.0.6 follow-redirects@1.15.9 --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
|
||||
npx clean-modules --directory nodejs --include "**/*.d.ts" "**/@types/**" "**/*.@(yaml|yml)" --yes
|
||||
npx clean-modules --directory nodejs "**/*.d.ts" "**/@types/**" "**/*.@(yaml|yml)" --yes
|
||||
rm sparticuz-chromium-*.tgz
|
||||
mkdir -p $(dir $@)
|
||||
zip -9 --filesync --move --recurse-paths $@ nodejs
|
||||
|
|
|
|||
251
README.md
251
README.md
|
|
@ -1,34 +1,37 @@
|
|||
# @sparticuz/chromium
|
||||
|
||||
[](https://www.npmjs.com/package/@sparticuz/chromium)
|
||||
[](https://www.typescriptlang.org/dt/search?search=chromium)
|
||||
[](bin/)
|
||||
[](bin/)
|
||||
[](https://www.npmjs.com/package/@sparticuz/chromium)
|
||||
[](https://www.npmjs.com/package/@sparticuz/chromium-min)
|
||||
[](https://paypal.me/sparticuz)
|
||||
|
||||
## Chromium for Serverless platforms
|
||||
|
||||
This package was originally forked from [alixaxel/chrome-aws-lambda#264](https://github.com/alixaxel/chrome-aws-lambda/pull/264).
|
||||
The biggest difference, besides the chromium version, is the inclusion of some code from https://github.com/alixaxel/lambdafs,
|
||||
as well as dropping that as a dependency. Due to some changes in WebGL, the files in bin/swiftshader.tar.br need to
|
||||
be extracted to `/tmp` instead of `/tmp/swiftshader`. This necessitated changes in lambdafs.
|
||||
[sparticuz/chrome-aws-lambda](https://github.com/sparticuz/chrome-aws-lambda) was originally forked from [alixaxel/chrome-aws-lambda#264](https://github.com/alixaxel/chrome-aws-lambda/pull/264).
|
||||
The biggest difference, besides the chromium version, is the inclusion of some code from https://github.com/alixaxel/lambdafs, as well as dropping that as a dependency. Due to some changes in WebGL, the files in bin/swiftshader.tar.br need to be extracted to `/tmp` instead of `/tmp/swiftshader`. This necessitated changes in lambdafs.
|
||||
|
||||
However, it quickly became difficult to maintain because of the pace of `puppeteer` updates. This package, `@sparticuz/chromium`,
|
||||
is not chained to `puppeteer` versions, but also does not include the overrides and hooks that the original package contained. It is only `chromium`, as well as the special code needed to decompress the brotli package.
|
||||
However, it quickly became difficult to maintain because of the pace of `puppeteer` updates. This package, `@sparticuz/chromium`, is not chained to `puppeteer` versions, but also does not include the overrides and hooks that the original package contained. It is only `chromium`, as well as the special code needed to decompress the brotli package, and a set of predefined arguments tailored to serverless usage.
|
||||
|
||||
## Install
|
||||
|
||||
[`puppeteer` ships with a prefered version of `chromium`](https://pptr.dev/faq/#q-why-doesnt-puppeteer-vxxx-work-with-chromium-vyyy).
|
||||
In order to figure out what version of `@sparticuz/chromium` you will need, please visit [Puppeteer's Chromium Support page](https://pptr.dev/chromium-support).
|
||||
[`puppeteer` ships with a preferred version of `chromium`](https://pptr.dev/faq/#q-why-doesnt-puppeteer-vxxx-work-with-chromium-vyyy). In order to figure out what version of `@sparticuz/chromium` you will need, please visit [Puppeteer's Chromium Support page](https://pptr.dev/chromium-support).
|
||||
|
||||
> For example, as of today, the latest version of `puppeteer` is `18.0.5`. The latest version of `chromium` stated on `puppeteer`'s support page is `106.0.5249.0`. So you need to install `@sparticuz/chromium@106`.
|
||||
|
||||
```shell
|
||||
# Puppeteer or Playwright is a production dependency
|
||||
npm install --save puppeteer-core@$PUPPETEER_VERSION
|
||||
# @sparticuz/chromium is a DEV dependency IF YOU ARE USING A LAYER, if not, use as a production dependency!
|
||||
# @sparticuz/chromium can be a DEV dependency IF YOU ARE USING A LAYER, if you are not using a layer, use as a production dependency!
|
||||
npm install --save-dev @sparticuz/chromium@$CHROMIUM_VERSION
|
||||
```
|
||||
|
||||
If your vendor does not allow large deploys (`chromium.br` is 50+ MB), you'll need to host the `chromium-v#-pack.tar` separately and use the [`@sparticuz/chromium-min` package](https://github.com/Sparticuz/chromium#-min-package).
|
||||
|
||||
```shell
|
||||
npm install --save @sparticuz/chromium-min@$CHROMIUM_VERSION
|
||||
```
|
||||
|
||||
If you wish to install an older version of Chromium, take a look at [@sparticuz/chrome-aws-lambda](https://github.com/Sparticuz/chrome-aws-lambda#versioning) or [@alixaxel/chrome-aws-lambda](https://github.com/alixaxel/chrome-aws-lambda).
|
||||
|
||||
## Versioning
|
||||
|
|
@ -36,22 +39,36 @@ If you wish to install an older version of Chromium, take a look at [@sparticuz/
|
|||
The @sparticuz/chromium version schema is as follows:
|
||||
`MajorChromiumVersion.MinorChromiumIncrement.@Sparticuz/chromiumPatchLevel`
|
||||
|
||||
Because this package follows Chromium's releases, it does NOT follow semantic versioning. **Breaking changes can occur with the 'patch' level.** Please check the release notes for information on breaking changes.
|
||||
|
||||
## Usage
|
||||
|
||||
This package works with all the currently supported AWS Lambda Node.js runtimes out of the box.
|
||||
|
||||
```javascript
|
||||
const test = requie("node:test");
|
||||
const test = require("node:test");
|
||||
const puppeteer = require("puppeteer-core");
|
||||
const chromium = require("@sparticuz/chromium");
|
||||
|
||||
// Optional: If you'd like to use the new headless mode. "shell" is the default.
|
||||
// NOTE: Because we build the shell binary, this option does not work.
|
||||
// However, this option will stay so when we migrate to full chromium it will work.
|
||||
chromium.setHeadlessMode = true;
|
||||
|
||||
// Optional: If you'd like to disable webgl, true is the default.
|
||||
chromium.setGraphicsMode = false;
|
||||
|
||||
// Optional: Load any fonts you need. Open Sans is included by default in AWS Lambda instances
|
||||
await chromium.font(
|
||||
"https://raw.githack.com/googlei18n/noto-emoji/master/fonts/NotoColorEmoji.ttf"
|
||||
);
|
||||
|
||||
test("Check the page title of example.com", async (t) => {
|
||||
const browser = await puppeteer.launch({
|
||||
args: chromium.args,
|
||||
defaultViewport: chromium.defaultViewport,
|
||||
executablePath: await chromium.executablePath,
|
||||
executablePath: await chromium.executablePath(),
|
||||
headless: chromium.headless,
|
||||
ignoreHTTPSErrors: true,
|
||||
});
|
||||
|
||||
const page = await browser.newPage();
|
||||
|
|
@ -68,13 +85,13 @@ test("Check the page title of example.com", async (t) => {
|
|||
```javascript
|
||||
const test = require("node:test");
|
||||
// Need to rename playwright's chromium object to something else
|
||||
const { chromium: playwright } = require('playwright-core');
|
||||
const chromium = require('@sparticuz/chromium');
|
||||
const { chromium: playwright } = require("playwright-core");
|
||||
const chromium = require("@sparticuz/chromium");
|
||||
|
||||
test("Check the page title of example.com", async (t) => {
|
||||
const browser = await playwright.launch({
|
||||
args: chromium.args,
|
||||
executablePath: await chromium.executablePath,
|
||||
executablePath: await chromium.executablePath(),
|
||||
headless: chromium.headless,
|
||||
});
|
||||
|
||||
|
|
@ -88,38 +105,167 @@ test("Check the page title of example.com", async (t) => {
|
|||
});
|
||||
```
|
||||
|
||||
You should allocate at least 512 MB of RAM to your Lambda, however 1600 MB (or more) is recommended.
|
||||
You should allocate at least 512 MB of RAM to your instance, however 1600 MB (or more) is recommended.
|
||||
|
||||
### Running Locally
|
||||
### -min package
|
||||
|
||||
This package will run in headless mode when `NODE_ENV = "test"`. If you want to run using your own local binary, set `IS_LOCAL` to anything.
|
||||
The -min package DOES NOT include the chromium brotli files. There are a few instances where this is useful. Primarily, this is useful when your host has file size limits.
|
||||
|
||||
## API
|
||||
To use the -min package please install the `@sparticuz/chromium-min` package.
|
||||
|
||||
| Method / Property | Returns | Description |
|
||||
| ----------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `font(url)` | `{?Promise<string>}` | Provisions a custom font and returns its basename. |
|
||||
| `args` | `{!Array<string>}` | Provides a list of recommended additional [Chromium flags](https://github.com/GoogleChrome/chrome-launcher/blob/master/docs/chrome-flags-for-tools.md). |
|
||||
| `defaultViewport` | `{!Object}` | Returns more sensible default viewport settings. |
|
||||
| `executablePath` | `{?Promise<string>}` | Returns the path the Chromium binary was extracted to. |
|
||||
| `headless` | `{!boolean}` | Returns `true` if we are running on AWS Lambda or GCF. |
|
||||
When using the -min package, you need to specify the location of the brotli files.
|
||||
|
||||
In this example, /opt/chromium contains all the brotli files
|
||||
|
||||
```
|
||||
/opt
|
||||
/chromium
|
||||
/aws.tar.br
|
||||
/chromium.br
|
||||
/swiftshader.tar.br
|
||||
```
|
||||
|
||||
```javascript
|
||||
const browser = await puppeteer.launch({
|
||||
args: chromium.args,
|
||||
defaultViewport: chromium.defaultViewport,
|
||||
executablePath: await chromium.executablePath("/opt/chromium"),
|
||||
headless: chromium.headless,
|
||||
});
|
||||
```
|
||||
|
||||
In the following example, https://www.example.com/chromiumPack.tar contains all the brotli files. Generally, this would be a location on S3, or another very fast downloadable location, that is in close proximity to your function's execution location.
|
||||
|
||||
On the initial iteration, `@sparticuz/chromium` will download the pack tar file, untar the files to `/tmp/chromium-pack`, then will un-brotli the `chromium` binary to `/tmp/chromium`. The following iterations will see that `/tmp/chromium` exists and will use the already downloaded files.
|
||||
|
||||
The latest chromium-pack.tar file will be on the latest [release](https://github.com/Sparticuz/chromium/releases).
|
||||
|
||||
```javascript
|
||||
const browser = await puppeteer.launch({
|
||||
args: chromium.args,
|
||||
defaultViewport: chromium.defaultViewport,
|
||||
executablePath: await chromium.executablePath(
|
||||
"https://www.example.com/chromiumPack.tar"
|
||||
),
|
||||
headless: chromium.headless,
|
||||
});
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
Here are some example projects and help with other services
|
||||
|
||||
- [Production Dependency](https://github.com/Sparticuz/chromium/tree/master/examples/production-dependency)
|
||||
- [Serverless Framework with Lambda Layer](https://github.com/Sparticuz/chromium/tree/master/examples/serverless-with-lambda-layer)
|
||||
- [Serverless Framework with Pre-existing Lambda Layer](https://github.com/Sparticuz/chromium/tree/master/examples/serverless-with-preexisting-lambda-layer)
|
||||
- [Chromium-min](https://github.com/Sparticuz/chromium/tree/master/examples/remote-min-binary)
|
||||
- [AWS SAM](https://github.com/Sparticuz/chromium/tree/master/examples/aws-sam)
|
||||
- [Webpack](https://github.com/Sparticuz/chromium/issues/24#issuecomment-1343196897)
|
||||
- [Netlify](https://github.com/Sparticuz/chromium/issues/24#issuecomment-1414107620)
|
||||
|
||||
### Running Locally & Headless/Headful mode
|
||||
|
||||
This version of `chromium` is built using the `headless.gn` build variables, which does not appear to even include a GUI. [Also, at this point, AWS Lambda 2 does not support a modern version of `glibc`](https://github.com/aws/aws-lambda-base-images/issues/59), so this package does not include an ARM version yet, which means it will not work on any M Series Apple products. If you need to test your code using a headful or ARM version, please use your locally installed version of `chromium/chrome`, or you may use the `puppeteer` provided version. Users have reported installing `rosetta` on MacOS will also work.
|
||||
|
||||
```shell
|
||||
npx @puppeteer/browsers install chromium@latest --path /tmp/localChromium
|
||||
```
|
||||
|
||||
For more information on installing a specific version of `chromium`, checkout [@puppeteer/browsers](https://www.npmjs.com/package/@puppeteer/browsers).
|
||||
|
||||
For example, you can set your code to use an ENV variable such as `IS_LOCAL`, then use if/else statements to direct puppeteer to the correct environment.
|
||||
|
||||
```javascript
|
||||
const browser = await puppeteer.launch({
|
||||
args: process.env.IS_LOCAL ? puppeteer.defaultArgs() : chromium.args,
|
||||
defaultViewport: chromium.defaultViewport,
|
||||
executablePath: process.env.IS_LOCAL
|
||||
? "/tmp/localChromium/chromium/linux-1122391/chrome-linux/chrome"
|
||||
: await chromium.executablePath(),
|
||||
headless: process.env.IS_LOCAL ? false : chromium.headless,
|
||||
});
|
||||
```
|
||||
|
||||
## Frequently asked questions
|
||||
|
||||
### Can I use ARM or Graviton instances?
|
||||
|
||||
Amazon's default Lambda base image is quite old at this point and does not support newer versions of `glibc` that chromium requires. When Amazon Linux 2023 comes to Lambda as the default base image, ARM support should be possible. Ref: https://github.com/Sparticuz/chrome-aws-lambda/pull/11, https://github.com/aws/aws-lambda-base-images/issues/59
|
||||
|
||||
### Can I use Google Chrome or Chrome for Testing, what is headless_shell?
|
||||
|
||||
`headless_shell` is a purpose built version of `chromium` specific for headless purposes. It does not include the GUI at all and only works via remote debugging connection. Ref: https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md, https://source.chromium.org/chromium/chromium/src/+/main:headless/app/headless_shell.cc
|
||||
|
||||
### Can I use the "new" Headless mode?
|
||||
|
||||
From what I can tell, `headless_shell` does not seem to include support for the "new" headless mode.
|
||||
|
||||
### It doesn't work with Webpack!?!
|
||||
|
||||
Try marking this package as an external. Ref: https://webpack.js.org/configuration/externals/
|
||||
|
||||
### I'm experiencing timeouts or failures closing Chromium
|
||||
|
||||
This is a common issue. Chromium sometimes opens up more pages than you ask for. You can try the following
|
||||
|
||||
```typescript
|
||||
for (const page of await browser.pages()) {
|
||||
await page.close();
|
||||
}
|
||||
await browser.close();
|
||||
```
|
||||
|
||||
You can also try the following if one of the calls is hanging for some reason.
|
||||
|
||||
```typescript
|
||||
await Promise.race([browser.close(), browser.close(), browser.close()]);
|
||||
```
|
||||
|
||||
Always `await browser.close()`, even if your script is returning an error.
|
||||
|
||||
### I need Accessible pdf files
|
||||
|
||||
This is due to the way @sparticuz/chromium is built. If you require accessible pdf's, you'll need to
|
||||
recompile chromium yourself with the following patch. You can then use that binary with @sparticuz/chromium-min.
|
||||
|
||||
_Note_: This will increase the time required to generate a PDF.
|
||||
|
||||
```patch
|
||||
diff --git a/_/ansible/plays/chromium.yml b/_/ansible/plays/chromium.yml
|
||||
index b42c740..49111d7 100644
|
||||
--- a/_/ansible/plays/chromium.yml
|
||||
+++ b/_/ansible/plays/chromium.yml
|
||||
@@ -249,8 +249,9 @@
|
||||
blink_symbol_level = 0
|
||||
dcheck_always_on = false
|
||||
disable_histogram_support = false
|
||||
- enable_basic_print_dialog = false
|
||||
enable_basic_printing = true
|
||||
+ enable_pdf = true
|
||||
+ enable_tagged_pdf = true
|
||||
enable_keystone_registration_framework = false
|
||||
enable_linux_installer = false
|
||||
enable_media_remoting = false
|
||||
```
|
||||
|
||||
## Fonts
|
||||
|
||||
The Amazon Linux 2 AWS Lambda runtime is no longer provisioned with any font faces.
|
||||
The Amazon Linux 2 AWS Lambda runtime is not provisioned with any font faces.
|
||||
|
||||
Because of this, this package ships with [Open Sans](https://fonts.google.com/specimen/Open+Sans), which supports the following scripts:
|
||||
|
||||
* Latin
|
||||
* Greek
|
||||
* Cyrillic
|
||||
- Latin
|
||||
- Greek
|
||||
- Cyrillic
|
||||
|
||||
To provision additional fonts, simply call the `font()` method with an absolute path or URL:
|
||||
|
||||
```typescript
|
||||
await chromium.font('/var/task/fonts/NotoColorEmoji.ttf');
|
||||
await chromium.font("/var/task/fonts/NotoColorEmoji.ttf");
|
||||
// or
|
||||
await chromium.font('https://raw.githack.com/googlei18n/noto-emoji/master/fonts/NotoColorEmoji.ttf');
|
||||
await chromium.font(
|
||||
"https://raw.githack.com/googlei18n/noto-emoji/master/fonts/NotoColorEmoji.ttf"
|
||||
);
|
||||
```
|
||||
|
||||
> `Noto Color Emoji` (or similar) is needed if you want to [render emojis](https://getemoji.com/).
|
||||
|
|
@ -128,13 +274,11 @@ await chromium.font('https://raw.githack.com/googlei18n/noto-emoji/master/fonts/
|
|||
|
||||
This method should be invoked _before_ launching Chromium.
|
||||
|
||||
> On non-serverless environments, the `font()` method is a no-op to avoid polluting the user space.
|
||||
|
||||
---
|
||||
|
||||
Alternatively, it's also possible to provision fonts via AWS Lambda Layers.
|
||||
|
||||
Simply create a directory named `.fonts` and place any font faces you want there:
|
||||
Simply create a directory named `.fonts` or `fonts` and place any font faces you want there:
|
||||
|
||||
```
|
||||
.fonts
|
||||
|
|
@ -145,8 +289,26 @@ Simply create a directory named `.fonts` and place any font faces you want there
|
|||
Afterwards, you just need to ZIP the directory and upload it as a AWS Lambda Layer:
|
||||
|
||||
```shell
|
||||
zip -9 --filesync --move --recurse-paths .fonts.zip .fonts/
|
||||
zip -9 --filesync --move --recurse-paths fonts.zip fonts/
|
||||
```
|
||||
|
||||
## Graphics
|
||||
|
||||
By default, this package uses `swiftshader`/`angle` to do CPU acceleration for WebGL. This is the only known way to enable WebGL on a serverless platform. You can disable WebGL by setting `chromium.setGraphiceMode = false;` _before_ launching Chromium. Disabling this will also skip the extract of the `bin/swiftshader.tar.br` file, which saves about a second of initial execution time. Disabling graphics is recommended if you know you are not using any WebGL.
|
||||
|
||||
## API
|
||||
|
||||
| Method / Property | Returns | Description |
|
||||
| ----------------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `font(url)` | `Promise<string>` | Provisions a custom font and returns its basename. |
|
||||
| `args` | `Array<string>` | Provides a list of recommended additional [Chromium flags](https://github.com/GoogleChrome/chrome-launcher/blob/master/docs/chrome-flags-for-tools.md). |
|
||||
| `defaultViewport` | `Object` | Returns a sensible default viewport for serverless. |
|
||||
| `executablePath(location?: string)` | `Promise<string>` | Returns the path the Chromium binary was extracted to. |
|
||||
| `setHeadlessMode` | `void` | Sets the headless mode to either `true` or `"shell"` |
|
||||
| `headless` | `true \| "shell"` | Returns `true` or `"shell"` depending on what version of chrome's headless you are running |
|
||||
| `setGraphicsMode` | `void` | Sets the graphics mode to either `true` or `false` |
|
||||
| `graphics` | `boolean` | Returns a boolean depending on whether webgl is enabled or disabled |
|
||||
|
||||
## Compiling
|
||||
|
||||
To compile your own version of Chromium check the [Ansible playbook instructions](_/ansible).
|
||||
|
|
@ -164,6 +326,7 @@ make chromium.zip
|
|||
```
|
||||
|
||||
The above will create a `chromium.zip` file, which can be uploaded to your Layers console. You can and should upload using the `aws cli`. (Replace the variables with your own values)
|
||||
|
||||
```shell
|
||||
bucketName="chromiumUploadBucket" && \
|
||||
versionNumber="107" && \
|
||||
|
|
@ -171,11 +334,7 @@ aws s3 cp chromium.zip "s3://${bucketName}/chromiumLayers/chromium${versionNumbe
|
|||
aws lambda publish-layer-version --layer-name chromium --description "Chromium v${versionNumber}" --content "S3Bucket=${bucketName},S3Key=chromiumLayers/chromium${versionNumber}.zip" --compatible-runtimes nodejs --compatible-architectures x86_64
|
||||
```
|
||||
|
||||
Alternatively, you can also download the layer artifact from one of our [CI workflow runs](https://github.com/Sparticuz/chromium/actions/workflows/aws.yml?query=is%3Asuccess+branch%3Amaster), however, they expire from Github after a certain time period.
|
||||
|
||||
## Google Cloud Functions
|
||||
|
||||
Since version `1.11.2`, it's also possible to use this package on Google/Firebase Cloud Functions.
|
||||
Alternatively, you can also download the layer artifact from one of our [releases](https://github.com/Sparticuz/chromium/releases).
|
||||
|
||||
According to our benchmarks, it's 40% to 50% faster than using the off-the-shelf `puppeteer` bundle.
|
||||
|
||||
|
|
@ -184,6 +343,8 @@ According to our benchmarks, it's 40% to 50% faster than using the off-the-shelf
|
|||
- Change the import or require to be `@sparticuz/chromium`
|
||||
- Add the import or require for `puppeteer-core`
|
||||
- Change the browser launch to use the native `puppeteer.launch()` function
|
||||
- Change the `executablePath` to be a function.
|
||||
|
||||
```diff
|
||||
-const chromium = require('@sparticuz/chrome-aws-lambda');
|
||||
+const chromium = require("@sparticuz/chromium");
|
||||
|
|
@ -198,7 +359,8 @@ exports.handler = async (event, context, callback) => {
|
|||
+ browser = await puppeteer.launch({
|
||||
args: chromium.args,
|
||||
defaultViewport: chromium.defaultViewport,
|
||||
executablePath: await chromium.executablePath,
|
||||
- executablePath: await chromium.executablePath,
|
||||
+ executablePath: await chromium.executablePath(),
|
||||
headless: chromium.headless,
|
||||
ignoreHTTPSErrors: true,
|
||||
});
|
||||
|
|
@ -219,6 +381,7 @@ exports.handler = async (event, context, callback) => {
|
|||
return callback(null, result);
|
||||
};
|
||||
```
|
||||
|
||||
## Compression
|
||||
|
||||
The Chromium binary is compressed using the Brotli algorithm.
|
||||
|
|
|
|||
|
|
@ -3,21 +3,14 @@
|
|||
"url": "https://example.com",
|
||||
"expected": {
|
||||
"title": "Example Domain",
|
||||
"screenshot": "72e10960dcf78c864f3d3635e3beb5be394daf40"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "https://example.com",
|
||||
"expected": {
|
||||
"title": "Example Domain",
|
||||
"screenshot": "72e10960dcf78c864f3d3635e3beb5be394daf40"
|
||||
"screenshot": "e610a8be5568f23c453b08928460aae3ae0b4b0a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "https://get.webgl.org",
|
||||
"expected": {
|
||||
"remove": "logo-container",
|
||||
"screenshot": "25ac96a4e44f338f5362c18da2b2823ee599c330"
|
||||
"screenshot": "ec6c79a571b4cb5727c6fc23f9da30de3868138c"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,47 +1,58 @@
|
|||
const { ok } = require('assert');
|
||||
const { createHash } = require('crypto');
|
||||
const { ok } = require("node:assert");
|
||||
const { createHash } = require("node:crypto");
|
||||
const puppeteer = require("puppeteer-core");
|
||||
const chromium = require('@sparticuz/chromium');
|
||||
const chromium = require("@sparticuz/chromium");
|
||||
|
||||
exports.handler = async (event, context) => {
|
||||
let browser = null;
|
||||
|
||||
try {
|
||||
const browser = await puppeteer.launch({
|
||||
browser = await puppeteer.launch({
|
||||
args: chromium.args,
|
||||
defaultViewport: chromium.defaultViewport,
|
||||
executablePath: await chromium.executablePath,
|
||||
dumpio: true,
|
||||
executablePath: await chromium.executablePath(),
|
||||
headless: chromium.headless,
|
||||
ignoreHTTPSErrors: true,
|
||||
acceptInsecureCerts: true,
|
||||
});
|
||||
|
||||
const contexts = [
|
||||
browser.defaultBrowserContext(),
|
||||
];
|
||||
console.log("Chromium version", await browser.version());
|
||||
|
||||
while (contexts.length < event.length) {
|
||||
contexts.push(await browser.createIncognitoBrowserContext());
|
||||
for (let job of event) {
|
||||
const page = await browser.newPage();
|
||||
|
||||
if (job.hasOwnProperty("url") === true) {
|
||||
await page.goto(job.url, { waitUntil: ["domcontentloaded", "load"] });
|
||||
|
||||
if (job.hasOwnProperty("expected") === true) {
|
||||
if (job.expected.hasOwnProperty("title") === true) {
|
||||
ok(
|
||||
(await page.title()) === job.expected.title,
|
||||
`Title assertion failed.`
|
||||
);
|
||||
}
|
||||
|
||||
for (let context of contexts) {
|
||||
const job = event.shift();
|
||||
const page = await context.newPage();
|
||||
|
||||
if (job.hasOwnProperty('url') === true) {
|
||||
await page.goto(job.url, { waitUntil: ['domcontentloaded', 'load'] });
|
||||
|
||||
if (job.hasOwnProperty('expected') === true) {
|
||||
if (job.expected.hasOwnProperty('title') === true) {
|
||||
ok(await page.title() === job.expected.title, `Title assertion failed.`);
|
||||
}
|
||||
|
||||
if (job.expected.hasOwnProperty('screenshot') === true) {
|
||||
if (job.expected.hasOwnProperty('remove') === true ) {
|
||||
if (job.expected.hasOwnProperty("screenshot") === true) {
|
||||
if (job.expected.hasOwnProperty("remove") === true) {
|
||||
await page.evaluate((selector) => {
|
||||
document.getElementById(selector).remove();
|
||||
}, job.expected.remove);
|
||||
}
|
||||
ok(createHash('sha1').update((await page.screenshot()).toString('base64')).digest('hex') === job.expected.screenshot, `Screenshot assertion failed.`);
|
||||
const screenshot = Buffer.from(await page.screenshot());
|
||||
/*
|
||||
console.log(
|
||||
`data:image/png;base64,${screenshot.toString("base64")}`,
|
||||
createHash("sha1")
|
||||
.update(screenshot.toString("base64"))
|
||||
.digest("hex")
|
||||
);
|
||||
*/
|
||||
ok(
|
||||
createHash("sha1")
|
||||
.update(screenshot.toString("base64"))
|
||||
.digest("hex") === job.expected.screenshot,
|
||||
`Screenshot assertion failed.`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -50,6 +61,9 @@ exports.handler = async (event, context) => {
|
|||
throw error.message;
|
||||
} finally {
|
||||
if (browser !== null) {
|
||||
for (const page of await browser.pages()) {
|
||||
await page.close();
|
||||
}
|
||||
await browser.close();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,20 +12,10 @@ Resources:
|
|||
LayerName: sparticuz-chromium
|
||||
ContentUri: code/
|
||||
CompatibleRuntimes:
|
||||
- nodejs14.x
|
||||
- nodejs16.x
|
||||
- nodejs18.x
|
||||
- nodejs20.x
|
||||
|
||||
node14:
|
||||
Type: AWS::Serverless::Function
|
||||
Properties:
|
||||
Layers:
|
||||
- !Ref layer
|
||||
Handler: handlers/index.handler
|
||||
Runtime: nodejs14.x
|
||||
Policies:
|
||||
- AWSLambdaBasicExecutionRole
|
||||
- AWSXRayDaemonWriteAccess
|
||||
Tracing: Active
|
||||
node16:
|
||||
Type: AWS::Serverless::Function
|
||||
Properties:
|
||||
|
|
@ -37,3 +27,25 @@ Resources:
|
|||
- AWSLambdaBasicExecutionRole
|
||||
- AWSXRayDaemonWriteAccess
|
||||
Tracing: Active
|
||||
node18:
|
||||
Type: AWS::Serverless::Function
|
||||
Properties:
|
||||
Layers:
|
||||
- !Ref layer
|
||||
Handler: handlers/index.handler
|
||||
Runtime: nodejs18.x
|
||||
Policies:
|
||||
- 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
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@
|
|||
[localhost:vars]
|
||||
ansible_connection=local
|
||||
ansible_python_interpreter=python
|
||||
image=ami-0bc441522038d8878
|
||||
image=ami-06c68f701d8090592
|
||||
region=us-east-1
|
||||
instance_size=c6i.12xlarge
|
||||
instance_size=c7i.12xlarge
|
||||
|
||||
[aws]
|
||||
|
||||
|
|
@ -14,4 +14,4 @@ instance_size=c6i.12xlarge
|
|||
ansible_connection=ssh
|
||||
ansible_python_interpreter=auto_silent
|
||||
ansible_ssh_private_key_file=ansible.pem
|
||||
chromium_revision=1056772
|
||||
chromium_revision=1343869
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@
|
|||
ebs:
|
||||
delete_on_termination: true
|
||||
volume_type: io2
|
||||
volume_size: 128
|
||||
volume_size: 256
|
||||
iops: 3000
|
||||
register: ec2
|
||||
|
||||
|
|
@ -71,7 +71,7 @@
|
|||
wait_for:
|
||||
host: "{{ ec2.instances[0].public_ip_address }}"
|
||||
port: 22
|
||||
timeout: 240
|
||||
timeout: 320
|
||||
state: started
|
||||
|
||||
- name: AWS
|
||||
|
|
@ -88,7 +88,7 @@
|
|||
become: true
|
||||
become_user: root
|
||||
shell: |
|
||||
dnf update --releasever=2022.0.20220831 -y
|
||||
dnf update --releasever=2022.0.20221207 -y
|
||||
|
||||
- name: Installing Packages
|
||||
become: true
|
||||
|
|
@ -142,8 +142,7 @@
|
|||
- name: Checking for Directory Structure
|
||||
stat:
|
||||
path: /srv/source/chromium
|
||||
register:
|
||||
structure
|
||||
register: structure
|
||||
|
||||
- name: Creating Directory Structure
|
||||
become: true
|
||||
|
|
@ -172,7 +171,7 @@
|
|||
dest: /srv/source/chromium/.gclient
|
||||
owner: ec2-user
|
||||
group: ec2-user
|
||||
mode: '0664'
|
||||
mode: "0664"
|
||||
|
||||
- name: Checking for Chromium
|
||||
stat:
|
||||
|
|
@ -211,22 +210,22 @@
|
|||
backrefs: yes
|
||||
with_items:
|
||||
- {
|
||||
path: 'sandbox_ipc_linux.cc',
|
||||
path: "sandbox_ipc_linux.cc",
|
||||
line: '\1PLOG(WARNING) << "poll"; failed_polls = 0;',
|
||||
regexp: '^(\s+)PLOG[(]WARNING[)] << "poll";$',
|
||||
}
|
||||
- {
|
||||
path: 'renderer_host/render_process_host_impl.cc',
|
||||
path: "renderer_host/render_process_host_impl.cc",
|
||||
line: '\1// \2\3',
|
||||
regexp: '^( )(\s*)(CHECK[(]render_process_host->InSameStoragePartition[(])$',
|
||||
}
|
||||
- {
|
||||
path: 'renderer_host/render_process_host_impl.cc',
|
||||
path: "renderer_host/render_process_host_impl.cc",
|
||||
line: '\1// \2\3',
|
||||
regexp: '^( )(\s*)(browser_context->GetStoragePartition[(]site_instance,)$',
|
||||
}
|
||||
- {
|
||||
path: 'renderer_host/render_process_host_impl.cc',
|
||||
path: "renderer_host/render_process_host_impl.cc",
|
||||
line: '\1// \2\3',
|
||||
regexp: '^( )(\s*)(false /[*] can_create [*]/[)][)][)];)$',
|
||||
}
|
||||
|
|
@ -237,14 +236,6 @@
|
|||
path: /srv/source/chromium/src/out/Headless
|
||||
state: directory
|
||||
|
||||
- name: Mounting Build Directory in Memory
|
||||
become: true
|
||||
become_user: root
|
||||
shell: |
|
||||
mount --types tmpfs --options size=24G,nr_inodes=128k,mode=1777 tmpfs /srv/source/chromium/src/out/Headless
|
||||
args:
|
||||
warn: false
|
||||
|
||||
- name: Creating Headless Chromium Configuration
|
||||
copy:
|
||||
content: |
|
||||
|
|
@ -257,7 +248,6 @@
|
|||
enable_keystone_registration_framework = false
|
||||
enable_linux_installer = false
|
||||
enable_media_remoting = false
|
||||
enable_one_click_signin = false
|
||||
ffmpeg_branding = "Chrome"
|
||||
is_component_build = false
|
||||
is_debug = false
|
||||
|
|
@ -266,7 +256,6 @@
|
|||
symbol_level = 0
|
||||
target_cpu = "x64"
|
||||
target_os = "linux"
|
||||
use_brlapi = 0
|
||||
use_sysroot = true
|
||||
v8_symbol_level = 0
|
||||
v8_target_cpu = "x64"
|
||||
|
|
@ -289,7 +278,6 @@
|
|||
sed --regexp-extended 's~[^0-9]+~~g' chrome/VERSION | tr '\n' '.' | sed 's~[.]$~~'
|
||||
args:
|
||||
chdir: /srv/source/chromium/src
|
||||
warn: false
|
||||
register: version
|
||||
|
||||
- name: Striping Symbols from Chromium Binary
|
||||
|
|
@ -321,7 +309,6 @@
|
|||
args:
|
||||
chdir: /srv/build/chromium
|
||||
creates: /srv/build/chromium/swiftshader.tar
|
||||
warn: false
|
||||
|
||||
- name: Compressing OpenGL ES driver
|
||||
shell: |
|
||||
|
|
@ -346,7 +333,7 @@
|
|||
amazon.aws.ec2_instance:
|
||||
wait: yes
|
||||
state: absent
|
||||
instance_ids: '{{ ec2.instance_ids }}'
|
||||
instance_ids: "{{ ec2.instance_ids }}"
|
||||
region: "{{ region }}"
|
||||
|
||||
- name: Deleting Security Group
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
BIN
bin/aws.tar.br
BIN
bin/aws.tar.br
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1 @@
|
|||
.aws-sam
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# Chromium as a Layer for AWS SAM
|
||||
|
||||
1. Install AWS SAM CLI: https://github.com/aws/aws-sam-cli/
|
||||
|
||||
1. Ensure Docker is installed and running: https://www.docker.com/
|
||||
|
||||
1. Build the project:
|
||||
|
||||
```sh
|
||||
sam build
|
||||
```
|
||||
|
||||
1. Invoke the AWS Lambda Function locally with:
|
||||
|
||||
```sh
|
||||
sam local invoke ExampleFunction
|
||||
```
|
||||
|
||||
This example connects to https://www.example.com and outputs the page's title as the function result. See the source code in [`app.mjs`](functions/exampleFunction/app.mjs) for more details.
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import chromium from '@sparticuz/chromium';
|
||||
import puppeteer from 'puppeteer-core';
|
||||
|
||||
export const lambdaHandler = async (event, context) => {
|
||||
const browser = await puppeteer.launch({
|
||||
args: chromium.args,
|
||||
defaultViewport: chromium.defaultViewport,
|
||||
executablePath: await chromium.executablePath(),
|
||||
headless: chromium.headless,
|
||||
});
|
||||
|
||||
const page = await browser.newPage();
|
||||
|
||||
await page.goto("https://www.example.com", { waitUntil: "networkidle0" });
|
||||
|
||||
const browserVersion = await browser.version();
|
||||
const pageTitle = await page.title();
|
||||
|
||||
await page.close();
|
||||
|
||||
await browser.close();
|
||||
|
||||
return { result: 'success', browserVersion, pageTitle };
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"name": "ExampleFunction",
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"description": "AWS Lambda Function that loads Chromium. Refer to https://github.com/Sparticuz/chromium#install for compatible versions.",
|
||||
"main": "app.mjs",
|
||||
"devDependencies": {
|
||||
"@sparticuz/chromium": "^119.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"puppeteer-core": "^21.5.1"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"name": "ChromiumLayer",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"description": "Chromium layer for AWS Lambda",
|
||||
"dependencies": {
|
||||
"@sparticuz/chromium": "^119.0.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
AWSTemplateFormatVersion: "2010-09-09"
|
||||
Transform: AWS::Serverless-2016-10-31
|
||||
Description: Example configuration for AWS SAM and Chromium
|
||||
|
||||
Resources:
|
||||
ChromiumLayer:
|
||||
Type: AWS::Serverless::LayerVersion
|
||||
Properties:
|
||||
Description: Chromium with Node.js integration for AWS Lambda
|
||||
ContentUri: layers/chromium
|
||||
CompatibleRuntimes:
|
||||
- &nodejsRuntime nodejs18.x
|
||||
# Chromium doesn't currently have ARM support; see https://github.com/Sparticuz/chromium#can-i-use-arm-or-graviton-instances
|
||||
CompatibleArchitectures:
|
||||
- &chromiumArch x86_64
|
||||
RetentionPolicy: Delete
|
||||
Metadata:
|
||||
BuildMethod: *nodejsRuntime
|
||||
BuildArchitecture: *chromiumArch
|
||||
|
||||
ExampleFunction:
|
||||
Type: AWS::Serverless::Function
|
||||
Properties:
|
||||
CodeUri: functions/exampleFunction
|
||||
Handler: app.lambdaHandler
|
||||
Runtime: *nodejsRuntime
|
||||
Architectures:
|
||||
- *chromiumArch
|
||||
Layers:
|
||||
- !Ref ChromiumLayer
|
||||
# Adjust as necessary
|
||||
Timeout: 30
|
||||
MemorySize: 1024
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
const puppeteer = require("puppeteer-core");
|
||||
const chromium = require("@sparticuz/chromium");
|
||||
|
||||
const handler = async () => {
|
||||
try {
|
||||
const browser = await puppeteer.launch({
|
||||
args: chromium.args,
|
||||
defaultViewport: chromium.defaultViewport,
|
||||
executablePath: await chromium.executablePath(),
|
||||
headless: chromium.headless,
|
||||
ignoreHTTPSErrors: true,
|
||||
});
|
||||
|
||||
const page = await browser.newPage();
|
||||
|
||||
await page.goto("https://www.example.com", { waitUntil: "networkidle0" });
|
||||
|
||||
console.log("Chromium:", await browser.version());
|
||||
console.log("Page Title:", await page.title());
|
||||
|
||||
await page.close();
|
||||
|
||||
await browser.close();
|
||||
} catch (error) {
|
||||
throw new Error(error.message);
|
||||
}
|
||||
};
|
||||
|
||||
handler().then(() => console.log("Done"));
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "chromium-production-dependency",
|
||||
"version": "0.0.0",
|
||||
"description": "This package demonstrates using @sparticuz/chromium as a production dependency. WARNING: This package is over 50 megabytes and will likely not deploy using anything other than self-host",
|
||||
"license": "ISC",
|
||||
"author": {
|
||||
"name": "Kyle McNally"
|
||||
},
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "node index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sparticuz/chromium": "110.0.0",
|
||||
"puppeteer-core": "19.6.3"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
const puppeteer = require("puppeteer-core");
|
||||
const chromium = require("@sparticuz/chromium-min");
|
||||
|
||||
const handler = async () => {
|
||||
try {
|
||||
const browser = await puppeteer.launch({
|
||||
args: chromium.args,
|
||||
defaultViewport: chromium.defaultViewport,
|
||||
executablePath: await chromium.executablePath(
|
||||
"https://github.com/Sparticuz/chromium/releases/download/v110.0.1/chromium-v110.0.1-pack.tar"
|
||||
),
|
||||
headless: chromium.headless,
|
||||
ignoreHTTPSErrors: true,
|
||||
});
|
||||
|
||||
const page = await browser.newPage();
|
||||
|
||||
await page.goto("https://www.example.com", { waitUntil: "networkidle0" });
|
||||
|
||||
console.log("Chromium:", await browser.version());
|
||||
console.log("Page Title:", await page.title());
|
||||
|
||||
await page.close();
|
||||
|
||||
await browser.close();
|
||||
} catch (error) {
|
||||
throw new Error(error.message);
|
||||
}
|
||||
};
|
||||
|
||||
handler().then(() => console.log("Done"));
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "chromium-remote-min",
|
||||
"version": "0.0.0",
|
||||
"description": "This package demonstrates using @sparticuz/chromium-min",
|
||||
"license": "ISC",
|
||||
"author": {
|
||||
"name": "Kyle McNally"
|
||||
},
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "node index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sparticuz/chromium-min": "110.0.1",
|
||||
"puppeteer-core": "19.6.3"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
const puppeteer = require("puppeteer-core");
|
||||
const chromium = require("@sparticuz/chromium");
|
||||
|
||||
module.exports = {
|
||||
handler: async () => {
|
||||
try {
|
||||
const browser = await puppeteer.launch({
|
||||
args: chromium.args,
|
||||
defaultViewport: chromium.defaultViewport,
|
||||
executablePath: await chromium.executablePath(),
|
||||
headless: chromium.headless,
|
||||
ignoreHTTPSErrors: true,
|
||||
});
|
||||
|
||||
const page = await browser.newPage();
|
||||
|
||||
await page.goto("https://www.example.com", { waitUntil: "networkidle0" });
|
||||
|
||||
console.log("Chromium:", await browser.version());
|
||||
console.log("Page Title:", await page.title());
|
||||
|
||||
await page.close();
|
||||
|
||||
await browser.close();
|
||||
} catch (error) {
|
||||
throw new Error(error.message);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "serverless-with-lambda-layer",
|
||||
"version": "0.0.0",
|
||||
"description": "This package demonstrates using @sparticuz/chromium as a devDependency with a layer that contains the binaries",
|
||||
"license": "ISC",
|
||||
"author": {
|
||||
"name": "Kyle McNally"
|
||||
},
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"deploy": "sls deploy",
|
||||
"test": "sls invoke --function chromium-test --log"
|
||||
},
|
||||
"dependencies": {
|
||||
"puppeteer-core": "19.6.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sparticuz/chromium": "110.0.0",
|
||||
"serverless": "^3.27.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
service: sls-with-layer
|
||||
|
||||
provider:
|
||||
name: aws
|
||||
runtime: nodejs18.x
|
||||
stage: dev
|
||||
region: us-east-1
|
||||
timeout: 300
|
||||
|
||||
functions:
|
||||
chromium-test:
|
||||
handler: index.handler
|
||||
layers:
|
||||
- !Ref ChromiumtestLambdaLayer
|
||||
|
||||
layers:
|
||||
chromiumtest:
|
||||
package:
|
||||
artifact: ../../chromium.zip
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
## Upload Lambda layer to AWS
|
||||
|
||||
1. Download the layer zip from Github Releases
|
||||

|
||||
2. Create a S3 bucket, or use a pre-existing bucket, upload the zip, and copy the URL
|
||||

|
||||
3. Create a new layer or use a pre-existing layer. (If using a pre-existing layer, Create a new verion)
|
||||

|
||||
4. Use the S3 file to load into to AWS Lambda Layers
|
||||

|
||||
5. Add the layer to your serverless function
|
||||
|
||||
```yaml
|
||||
service: sls-with-preexisting-layer
|
||||
|
||||
provider:
|
||||
name: aws
|
||||
runtime: nodejs18.x
|
||||
stage: dev
|
||||
region: us-east-1
|
||||
timeout: 300
|
||||
|
||||
functions:
|
||||
chromium-test:
|
||||
handler: index.handler
|
||||
layers:
|
||||
- arn:aws:lambda:us-east-1:************:layer:chromium:*
|
||||
```
|
||||
|
||||
# BONUS
|
||||
|
||||
These steps can easily be automated using the following code:
|
||||
|
||||
```shell
|
||||
$ chromiumVersion="112.0.0"
|
||||
$ bucketName="chromiumUploadBucket"
|
||||
$ wget "https://github.com/Sparticuz/chromium/releases/download/v${chromiumVersion}/chromium-v${chromiumVersion}-layer.zip"
|
||||
$ aws s3 cp "chromium-v${chromiumVersion}-layer.zip" "s3://${bucketName}/chromiumLayers/chromium-v${chromiumVersion}-layer.zip"
|
||||
$ aws lambda publish-layer-version --layer-name chromium --description "Chromium v${chromiumVersion}" --content "S3Bucket=${bucketName},S3Key=chromiumLayers/chromium-v${chromiumVersion}-layer.zip" --compatible-runtimes nodejs --compatible-architectures x86_64
|
||||
```
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 117 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
|
|
@ -0,0 +1,29 @@
|
|||
const puppeteer = require("puppeteer-core");
|
||||
const chromium = require("@sparticuz/chromium");
|
||||
|
||||
module.exports = {
|
||||
handler: async () => {
|
||||
try {
|
||||
const browser = await puppeteer.launch({
|
||||
args: chromium.args,
|
||||
defaultViewport: chromium.defaultViewport,
|
||||
executablePath: await chromium.executablePath(),
|
||||
headless: chromium.headless,
|
||||
ignoreHTTPSErrors: true,
|
||||
});
|
||||
|
||||
const page = await browser.newPage();
|
||||
|
||||
await page.goto("https://www.example.com", { waitUntil: "networkidle0" });
|
||||
|
||||
console.log("Chromium:", await browser.version());
|
||||
console.log("Page Title:", await page.title());
|
||||
|
||||
await page.close();
|
||||
|
||||
await browser.close();
|
||||
} catch (error) {
|
||||
throw new Error(error.message);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "serverless-with-lambda-layer",
|
||||
"version": "0.0.0",
|
||||
"description": "This package demonstrates using @sparticuz/chromium as a devDependency with a layer that contains the binaries",
|
||||
"license": "ISC",
|
||||
"author": {
|
||||
"name": "Kyle McNally"
|
||||
},
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"deploy": "sls deploy",
|
||||
"test": "sls invoke --function chromium-test --log"
|
||||
},
|
||||
"dependencies": {
|
||||
"puppeteer-core": "19.6.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sparticuz/chromium": "110.0.0",
|
||||
"serverless": "^3.27.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
service: sls-with-layer
|
||||
|
||||
provider:
|
||||
name: aws
|
||||
runtime: nodejs18.x
|
||||
stage: dev
|
||||
region: us-east-1
|
||||
timeout: 300
|
||||
|
||||
functions:
|
||||
chromium-test:
|
||||
handler: index.handler
|
||||
layers:
|
||||
- arn:aws:lambda:us-east-1:************:layer:chromium:*
|
||||
|
|
@ -0,0 +1,331 @@
|
|||
{
|
||||
"name": "@sparticuz/chromium",
|
||||
"version": "130.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@sparticuz/chromium",
|
||||
"version": "130.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.9",
|
||||
"tar-fs": "^3.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tsconfig/node20": "^20.1.4",
|
||||
"@tsconfig/strictest": "^2.0.5",
|
||||
"@types/follow-redirects": "^1.14.4",
|
||||
"@types/node": "^20.16.10",
|
||||
"@types/tar-fs": "^2.0.4",
|
||||
"clean-modules": "^3.1.1",
|
||||
"typescript": "^5.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
}
|
||||
},
|
||||
"node_modules/@tsconfig/node20": {
|
||||
"version": "20.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node20/-/node20-20.1.4.tgz",
|
||||
"integrity": "sha512-sqgsT69YFeLWf5NtJ4Xq/xAF8p4ZQHlmGW74Nu2tD4+g5fAsposc4ZfaaPixVu4y01BEiDCWLRDCvDM5JOsRxg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@tsconfig/strictest": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/strictest/-/strictest-2.0.5.tgz",
|
||||
"integrity": "sha512-ec4tjL2Rr0pkZ5hww65c+EEPYwxOi4Ryv+0MtjeaSQRJyq322Q27eOQiFbuNgw2hpL4hB1/W/HBGk3VKS43osg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/follow-redirects": {
|
||||
"version": "1.14.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/follow-redirects/-/follow-redirects-1.14.4.tgz",
|
||||
"integrity": "sha512-GWXfsD0Jc1RWiFmMuMFCpXMzi9L7oPDVwxUnZdg89kDNnqsRfUKXEtUYtA98A6lig1WXH/CYY/fvPW9HuN5fTA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.16.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz",
|
||||
"integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.19.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/tar-fs": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/tar-fs/-/tar-fs-2.0.4.tgz",
|
||||
"integrity": "sha512-ipPec0CjTmVDWE+QKr9cTmIIoTl7dFG/yARCM5MqK8i6CNLIG1P8x4kwDsOQY1ChZOZjH0wO9nvfgBvWl4R3kA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"@types/tar-stream": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/tar-stream": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/tar-stream/-/tar-stream-2.2.2.tgz",
|
||||
"integrity": "sha512-1AX+Yt3icFuU6kxwmPakaiGrJUwG44MpuiqPg4dSolRFk6jmvs4b3IbUol9wKDLIgU76gevn3EwE8y/DkSJCZQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/b4a": {
|
||||
"version": "1.6.4",
|
||||
"resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz",
|
||||
"integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw=="
|
||||
},
|
||||
"node_modules/bare-events": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.2.0.tgz",
|
||||
"integrity": "sha512-Yyyqff4PIFfSuthCZqLlPISTWHmnQxoPuAvkmgzsJEmG3CesdIv6Xweayl0JkCZJSB2yYIdJyEz97tpxNhgjbg==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/bare-fs": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.1.5.tgz",
|
||||
"integrity": "sha512-5t0nlecX+N2uJqdxe9d18A98cp2u9BETelbjKpiVgQqzzmVNFYWEAjQHqS+2Khgto1vcwhik9cXucaj5ve2WWA==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"bare-events": "^2.0.0",
|
||||
"bare-os": "^2.0.0",
|
||||
"bare-path": "^2.0.0",
|
||||
"streamx": "^2.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bare-os": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.2.0.tgz",
|
||||
"integrity": "sha512-hD0rOPfYWOMpVirTACt4/nK8mC55La12K5fY1ij8HAdfQakD62M+H4o4tpfKzVGLgRDTuk3vjA4GqGXXCeFbag==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/bare-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.0.tgz",
|
||||
"integrity": "sha512-DIIg7ts8bdRKwJRJrUMy/PICEaQZaPGZ26lsSx9MJSwIhSrcdHn7/C8W+XmnG/rKi6BaRcz+JO00CjZteybDtw==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"bare-os": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/clean-modules": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clean-modules/-/clean-modules-3.1.1.tgz",
|
||||
"integrity": "sha512-t/7dNtn6vQYxujYxdwZeLa0NsLE92KQ0XeV3CDJ2TXgLTvn3ijmjlQN0Dm9wjYQgC0miZiF66ClTQzgIeYw96A==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"clipanion": "^3.2.1",
|
||||
"picomatch": "^2.3.0",
|
||||
"pretty-bytes": "^6.1.0",
|
||||
"pretty-ms": "^8.0.0",
|
||||
"supports-color": "^9.4.0"
|
||||
},
|
||||
"bin": {
|
||||
"clean-modules": "bin/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/clipanion": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/clipanion/-/clipanion-3.2.1.tgz",
|
||||
"integrity": "sha512-dYFdjLb7y1ajfxQopN05mylEpK9ZX0sO1/RfMXdfmwjlIsPkbh4p7A682x++zFPLDCo1x3p82dtljHf5cW2LKA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"typanion": "^3.8.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typanion": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/end-of-stream": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||
"dependencies": {
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-fifo": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.0.tgz",
|
||||
"integrity": "sha512-IgfweLvEpwyA4WgiQe9Nx6VV2QkML2NkvZnk1oKnIzXgXdWxuhF7zw4DvLTPZJn6PIUneiAXPF24QmoEqHTjyw=="
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.9",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
||||
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/parse-ms": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-3.0.0.tgz",
|
||||
"integrity": "sha512-Tpb8Z7r7XbbtBTrM9UhpkzzaMrqA2VXMT3YChzYltwV3P3pM6t8wl7TvpMnSTosz1aQAdVib7kdoys7vYOPerw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/pretty-bytes": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz",
|
||||
"integrity": "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/pretty-ms": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-8.0.0.tgz",
|
||||
"integrity": "sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"parse-ms": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/pump": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
||||
"dependencies": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/queue-tick": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz",
|
||||
"integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag=="
|
||||
},
|
||||
"node_modules/streamx": {
|
||||
"version": "2.15.1",
|
||||
"resolved": "https://registry.npmjs.org/streamx/-/streamx-2.15.1.tgz",
|
||||
"integrity": "sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA==",
|
||||
"dependencies": {
|
||||
"fast-fifo": "^1.1.0",
|
||||
"queue-tick": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "9.4.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz",
|
||||
"integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/tar-fs": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz",
|
||||
"integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==",
|
||||
"dependencies": {
|
||||
"pump": "^3.0.0",
|
||||
"tar-stream": "^3.1.5"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"bare-fs": "^2.1.1",
|
||||
"bare-path": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tar-stream": {
|
||||
"version": "3.1.6",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.6.tgz",
|
||||
"integrity": "sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==",
|
||||
"dependencies": {
|
||||
"b4a": "^1.6.4",
|
||||
"fast-fifo": "^1.2.0",
|
||||
"streamx": "^2.15.0"
|
||||
}
|
||||
},
|
||||
"node_modules/typanion": {
|
||||
"version": "3.14.0",
|
||||
"resolved": "https://registry.npmjs.org/typanion/-/typanion-3.14.0.tgz",
|
||||
"integrity": "sha512-ZW/lVMRabETuYCd9O9ZvMhAh8GslSqaUjxmK/JLPCh6l73CvLBiuXswj/+7LdnWOgYsQ130FqLzFz5aGT4I3Ug==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.6.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz",
|
||||
"integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.19.6",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.6.tgz",
|
||||
"integrity": "sha512-e/vggGopEfTKSvj4ihnOLTsqhrKRN3LeO6qSN/GxohhuRv8qH9bNQ4B8W7e/vFL+0XTnmHPB4/kegunZGA4Org==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
}
|
||||
}
|
||||
}
|
||||
83
package.json
83
package.json
|
|
@ -1,41 +1,7 @@
|
|||
{
|
||||
"name": "@sparticuz/chromium",
|
||||
"version": "108.0.0",
|
||||
"author": {
|
||||
"name": "Kyle McNally"
|
||||
},
|
||||
"license": "MIT",
|
||||
"version": "130.0.0",
|
||||
"description": "Chromium Binary for Serverless Platforms",
|
||||
"main": "build/index.js",
|
||||
"types": "build/index.d.ts",
|
||||
"files": [
|
||||
"bin",
|
||||
"build"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "make clean && make && make pretest && make test",
|
||||
"build": "rm -rf build && tsc -p tsconfig.json",
|
||||
"postversion": "git push && git push --tags && npm publish",
|
||||
"prepack": "npm run build",
|
||||
"preversion": "npm run build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.11.62",
|
||||
"@types/tar-fs": "^2.0.1",
|
||||
"clean-modules": "^2.0.6",
|
||||
"typescript": "^4.8.3"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/Sparticuz/chromium/issues"
|
||||
},
|
||||
"homepage": "https://github.com/Sparticuz/chromium",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/Sparticuz/chromium.git"
|
||||
},
|
||||
"keywords": [
|
||||
"aws",
|
||||
"browser",
|
||||
|
|
@ -46,18 +12,43 @@
|
|||
"playwright",
|
||||
"serverless"
|
||||
],
|
||||
"prettier": {
|
||||
"arrowParens": "always",
|
||||
"bracketSpacing": true,
|
||||
"jsxBracketSameLine": false,
|
||||
"printWidth": 140,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5",
|
||||
"useTabs": false
|
||||
"homepage": "https://github.com/Sparticuz/chromium",
|
||||
"bugs": {
|
||||
"url": "https://github.com/Sparticuz/chromium/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/Sparticuz/chromium.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
"name": "Kyle McNally"
|
||||
},
|
||||
"type": "commonjs",
|
||||
"main": "build/index.js",
|
||||
"types": "build/index.d.ts",
|
||||
"files": [
|
||||
"bin",
|
||||
"build"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "rm -rf build && tsc -p tsconfig.json",
|
||||
"test": "make clean && make && make pretest && make test"
|
||||
},
|
||||
"dependencies": {
|
||||
"tar-fs": "^2.1.1"
|
||||
"follow-redirects": "^1.15.9",
|
||||
"tar-fs": "^3.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tsconfig/node20": "^20.1.4",
|
||||
"@tsconfig/strictest": "^2.0.5",
|
||||
"@types/follow-redirects": "^1.14.4",
|
||||
"@types/node": "^20.16.10",
|
||||
"@types/tar-fs": "^2.0.4",
|
||||
"clean-modules": "^3.1.1",
|
||||
"typescript": "^5.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
import { unlink } from "node:fs";
|
||||
import { https } from "follow-redirects";
|
||||
import { tmpdir } from "node:os";
|
||||
import { extract } from "tar-fs";
|
||||
import { parse } from "node:url";
|
||||
import type { UrlWithStringQuery } from "node:url";
|
||||
|
||||
interface FollowRedirOptions extends UrlWithStringQuery {
|
||||
maxBodyLength: number;
|
||||
}
|
||||
|
||||
export const isValidUrl = (input: string) => {
|
||||
try {
|
||||
return !!new URL(input);
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if the running instance is inside an AWS Lambda container.
|
||||
* AWS_EXECUTION_ENV is for native Lambda instances
|
||||
* AWS_LAMBDA_JS_RUNTIME is for netlify instances
|
||||
* @returns boolean indicating if the running instance is inside a Lambda container
|
||||
*/
|
||||
export const isRunningInAwsLambda = () => {
|
||||
if (
|
||||
process.env["AWS_EXECUTION_ENV"] &&
|
||||
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"] &&
|
||||
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 false;
|
||||
};
|
||||
|
||||
export const downloadAndExtract = async (url: string) =>
|
||||
new Promise<string>((resolve, reject) => {
|
||||
const getOptions = parse(url) as FollowRedirOptions;
|
||||
getOptions.maxBodyLength = 60 * 1024 * 1024; // 60mb
|
||||
const destDir = `${tmpdir()}/chromium-pack`;
|
||||
const extractObj = extract(destDir);
|
||||
https
|
||||
.get(url, (response) => {
|
||||
response.pipe(extractObj);
|
||||
extractObj.on("finish", () => {
|
||||
resolve(destDir);
|
||||
});
|
||||
})
|
||||
.on("error", (err) => {
|
||||
unlink(destDir, (_) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
408
source/index.ts
408
source/index.ts
|
|
@ -1,8 +1,20 @@
|
|||
import { access, createWriteStream, existsSync, mkdirSync, readdirSync, symlink, unlinkSync } from 'fs';
|
||||
import { IncomingMessage } from 'http';
|
||||
import LambdaFS from './lambdafs';
|
||||
import { join } from 'path';
|
||||
import { URL } from 'url';
|
||||
import {
|
||||
access,
|
||||
createWriteStream,
|
||||
existsSync,
|
||||
mkdirSync,
|
||||
symlink,
|
||||
} from "node:fs";
|
||||
import { https } from "follow-redirects";
|
||||
import LambdaFS from "./lambdafs";
|
||||
import { join } from "node:path";
|
||||
import { URL } from "node:url";
|
||||
import {
|
||||
downloadAndExtract,
|
||||
isRunningInAwsLambda,
|
||||
isValidUrl,
|
||||
isRunningInAwsLambdaNode20,
|
||||
} from "./helper";
|
||||
|
||||
/** Viewport taken from https://github.com/puppeteer/puppeteer/blob/main/docs/api/puppeteer.viewport.md */
|
||||
interface Viewport {
|
||||
|
|
@ -17,54 +29,89 @@ interface Viewport {
|
|||
/**
|
||||
* Specify device scale factor.
|
||||
* See {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio | devicePixelRatio} for more info.
|
||||
* @defaultValue 1
|
||||
* @default 1
|
||||
*/
|
||||
deviceScaleFactor?: number;
|
||||
/**
|
||||
* Whether the `meta viewport` tag is taken into account.
|
||||
* @defaultValue false
|
||||
* @default false
|
||||
*/
|
||||
isMobile?: boolean;
|
||||
/**
|
||||
* Specifies if the viewport is in landscape mode.
|
||||
* @defaultValue false
|
||||
* @default false
|
||||
*/
|
||||
isLandscape?: boolean;
|
||||
/**
|
||||
* Specify if the viewport supports touch events.
|
||||
* @defaultValue false
|
||||
* @default false
|
||||
*/
|
||||
hasTouch?: boolean;
|
||||
}
|
||||
|
||||
if (/^AWS_Lambda_nodejs(?:10|12|14|16)[.]x$/.test(process.env.AWS_EXECUTION_ENV) === true) {
|
||||
if (process.env.FONTCONFIG_PATH === undefined) {
|
||||
process.env.FONTCONFIG_PATH = '/tmp/aws';
|
||||
if (isRunningInAwsLambda()) {
|
||||
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/aws/lib';
|
||||
} else if (process.env.LD_LIBRARY_PATH.startsWith('/tmp/aws/lib') !== true) {
|
||||
process.env.LD_LIBRARY_PATH = [...new Set(['/tmp/aws/lib', ...process.env.LD_LIBRARY_PATH.split(':')])].join(':');
|
||||
if (process.env["LD_LIBRARY_PATH"] === undefined) {
|
||||
process.env["LD_LIBRARY_PATH"] = "/tmp/al2/lib";
|
||||
} else if (
|
||||
process.env["LD_LIBRARY_PATH"].startsWith("/tmp/al2/lib") !== true
|
||||
) {
|
||||
process.env["LD_LIBRARY_PATH"] = [
|
||||
...new Set([
|
||||
"/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(":");
|
||||
}
|
||||
}
|
||||
|
||||
class Chromium {
|
||||
/**
|
||||
* Determines the headless mode that chromium will run at
|
||||
* https://developer.chrome.com/articles/new-headless/#try-out-the-new-headless
|
||||
* @values true or "new"
|
||||
*/
|
||||
private static headlessMode: true | "shell" = "shell";
|
||||
|
||||
/**
|
||||
* If true, the graphics stack and webgl is enabled,
|
||||
* If false, webgl will be disabled.
|
||||
* (If false, the swiftshader.tar.br file will also not extract)
|
||||
*/
|
||||
private static graphicsMode: boolean = true;
|
||||
|
||||
/**
|
||||
* Downloads or symlinks a custom font and returns its basename, patching the environment so that Chromium can find it.
|
||||
* If not running on AWS Lambda nor Google Cloud Functions, `null` is returned instead.
|
||||
*/
|
||||
static font(input: string): Promise<string> {
|
||||
if (Chromium.headless !== true) {
|
||||
return null;
|
||||
if (process.env["HOME"] === undefined) {
|
||||
process.env["HOME"] = "/tmp";
|
||||
}
|
||||
|
||||
if (process.env.HOME === undefined) {
|
||||
process.env.HOME = '/tmp';
|
||||
}
|
||||
|
||||
if (existsSync(`${process.env.HOME}/.fonts`) !== true) {
|
||||
mkdirSync(`${process.env.HOME}/.fonts`);
|
||||
if (existsSync(`${process.env["HOME"]}/.fonts`) !== true) {
|
||||
mkdirSync(`${process.env["HOME"]}/.fonts`);
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
|
|
@ -73,43 +120,45 @@ class Chromium {
|
|||
}
|
||||
|
||||
const url = new URL(input);
|
||||
const output = `${process.env.HOME}/.fonts/${url.pathname.split('/').pop()}`;
|
||||
const output = `${process.env["HOME"]}/.fonts/${url.pathname
|
||||
.split("/")
|
||||
.pop()}`;
|
||||
|
||||
if (existsSync(output) === true) {
|
||||
return resolve(output.split('/').pop());
|
||||
return resolve(output.split("/").pop() as string);
|
||||
}
|
||||
|
||||
if (url.protocol === 'file:') {
|
||||
if (url.protocol === "file:") {
|
||||
access(url.pathname, (error) => {
|
||||
if (error != null) {
|
||||
return reject(error);
|
||||
}
|
||||
|
||||
symlink(url.pathname, output, (error) => {
|
||||
return error != null ? reject(error) : resolve(url.pathname.split('/').pop());
|
||||
return error != null
|
||||
? reject(error)
|
||||
: resolve(url.pathname.split("/").pop() as string);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
let handler = url.protocol === 'http:' ? require('http').get : require('https').get;
|
||||
|
||||
handler(input, (response: IncomingMessage) => {
|
||||
https.get(input, (response) => {
|
||||
if (response.statusCode !== 200) {
|
||||
return reject(`Unexpected status code: ${response.statusCode}.`);
|
||||
}
|
||||
|
||||
const stream = createWriteStream(output);
|
||||
|
||||
stream.once('error', (error) => {
|
||||
stream.once("error", (error) => {
|
||||
return reject(error);
|
||||
});
|
||||
|
||||
response.on('data', (chunk) => {
|
||||
response.on("data", (chunk) => {
|
||||
stream.write(chunk);
|
||||
});
|
||||
|
||||
response.once('end', () => {
|
||||
response.once("end", () => {
|
||||
stream.end(() => {
|
||||
return resolve(url.pathname.split('/').pop());
|
||||
return resolve(url.pathname.split("/").pop() as string);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -122,47 +171,113 @@ class Chromium {
|
|||
* The canonical list of flags can be found on https://peter.sh/experiments/chromium-command-line-switches/.
|
||||
*/
|
||||
static get args(): string[] {
|
||||
const result = [
|
||||
'--allow-running-insecure-content', // https://source.chromium.org/search?q=lang:cpp+symbol:kAllowRunningInsecureContent&ss=chromium
|
||||
'--autoplay-policy=user-gesture-required', // https://source.chromium.org/search?q=lang:cpp+symbol:kAutoplayPolicy&ss=chromium
|
||||
'--disable-background-timer-throttling',
|
||||
'--disable-component-update', // https://source.chromium.org/search?q=lang:cpp+symbol:kDisableComponentUpdate&ss=chromium
|
||||
'--disable-domain-reliability', // https://source.chromium.org/search?q=lang:cpp+symbol:kDisableDomainReliability&ss=chromium
|
||||
'--disable-features=AudioServiceOutOfProcess,IsolateOrigins,site-per-process', // https://source.chromium.org/search?q=file:content_features.cc&ss=chromium
|
||||
'--disable-ipc-flooding-protection',
|
||||
'--disable-print-preview', // https://source.chromium.org/search?q=lang:cpp+symbol:kDisablePrintPreview&ss=chromium
|
||||
'--disable-dev-shm-usage',
|
||||
'--disable-setuid-sandbox', // https://source.chromium.org/search?q=lang:cpp+symbol:kDisableSetuidSandbox&ss=chromium
|
||||
'--disable-site-isolation-trials', // https://source.chromium.org/search?q=lang:cpp+symbol:kDisableSiteIsolation&ss=chromium
|
||||
'--disable-speech-api', // https://source.chromium.org/search?q=lang:cpp+symbol:kDisableSpeechAPI&ss=chromium
|
||||
'--disable-web-security', // https://source.chromium.org/search?q=lang:cpp+symbol:kDisableWebSecurity&ss=chromium
|
||||
'--disk-cache-size=33554432', // https://source.chromium.org/search?q=lang:cpp+symbol:kDiskCacheSize&ss=chromium
|
||||
'--enable-features=SharedArrayBuffer', // https://source.chromium.org/search?q=file:content_features.cc&ss=chromium
|
||||
'--hide-scrollbars', // https://source.chromium.org/search?q=lang:cpp+symbol:kHideScrollbars&ss=chromium
|
||||
'--ignore-gpu-blocklist', // https://source.chromium.org/search?q=lang:cpp+symbol:kIgnoreGpuBlocklist&ss=chromium
|
||||
'--in-process-gpu', // https://source.chromium.org/search?q=lang:cpp+symbol:kInProcessGPU&ss=chromium
|
||||
'--mute-audio', // https://source.chromium.org/search?q=lang:cpp+symbol:kMuteAudio&ss=chromium
|
||||
'--no-default-browser-check', // https://source.chromium.org/search?q=lang:cpp+symbol:kNoDefaultBrowserCheck&ss=chromium
|
||||
'--no-first-run',
|
||||
'--no-pings', // https://source.chromium.org/search?q=lang:cpp+symbol:kNoPings&ss=chromium
|
||||
'--no-sandbox', // https://source.chromium.org/search?q=lang:cpp+symbol:kNoSandbox&ss=chromium
|
||||
'--no-zygote', // https://source.chromium.org/search?q=lang:cpp+symbol:kNoZygote&ss=chromium
|
||||
'--use-gl=angle', // https://chromium.googlesource.com/chromium/src/+/main/docs/gpu/swiftshader.md
|
||||
'--use-angle=swiftshader', // https://chromium.googlesource.com/chromium/src/+/main/docs/gpu/swiftshader.md
|
||||
'--window-size=1920,1080', // https://source.chromium.org/search?q=lang:cpp+symbol:kWindowSize&ss=chromium
|
||||
/**
|
||||
* These are the default args in puppeteer.
|
||||
* https://github.com/puppeteer/puppeteer/blob/3a31070d054fa3cd8116ca31c578807ed8d6f987/packages/puppeteer-core/src/node/ChromeLauncher.ts#L185
|
||||
*/
|
||||
const puppeteerFlags = [
|
||||
"--allow-pre-commit-input",
|
||||
"--disable-background-networking",
|
||||
"--disable-background-timer-throttling",
|
||||
"--disable-backgrounding-occluded-windows",
|
||||
"--disable-breakpad",
|
||||
"--disable-client-side-phishing-detection",
|
||||
"--disable-component-extensions-with-background-pages",
|
||||
"--disable-component-update",
|
||||
"--disable-default-apps",
|
||||
"--disable-dev-shm-usage",
|
||||
"--disable-extensions",
|
||||
"--disable-hang-monitor",
|
||||
"--disable-ipc-flooding-protection",
|
||||
"--disable-popup-blocking",
|
||||
"--disable-prompt-on-repost",
|
||||
"--disable-renderer-backgrounding",
|
||||
"--disable-sync",
|
||||
"--enable-automation",
|
||||
// TODO(sadym): remove '--enable-blink-features=IdleDetection' once
|
||||
// IdleDetection is turned on by default.
|
||||
"--enable-blink-features=IdleDetection",
|
||||
"--export-tagged-pdf",
|
||||
"--force-color-profile=srgb",
|
||||
"--metrics-recording-only",
|
||||
"--no-first-run",
|
||||
"--password-store=basic",
|
||||
"--use-mock-keychain",
|
||||
];
|
||||
const puppeteerDisableFeatures = [
|
||||
"Translate",
|
||||
"BackForwardCache",
|
||||
// AcceptCHFrame disabled because of crbug.com/1348106.
|
||||
"AcceptCHFrame",
|
||||
"MediaRouter",
|
||||
"OptimizationHints",
|
||||
];
|
||||
const puppeteerEnableFeatures = ["NetworkServiceInProcess2"];
|
||||
|
||||
const chromiumFlags = [
|
||||
"--disable-domain-reliability", // https://github.com/GoogleChrome/chrome-launcher/blob/main/docs/chrome-flags-for-tools.md#background-networking
|
||||
"--disable-print-preview", // https://source.chromium.org/search?q=lang:cpp+symbol:kDisablePrintPreview&ss=chromium
|
||||
"--disable-speech-api", // https://source.chromium.org/search?q=lang:cpp+symbol:kDisableSpeechAPI&ss=chromium
|
||||
"--disk-cache-size=33554432", // https://source.chromium.org/search?q=lang:cpp+symbol:kDiskCacheSize&ss=chromium
|
||||
"--mute-audio", // https://source.chromium.org/search?q=lang:cpp+symbol:kMuteAudio&ss=chromium
|
||||
"--no-default-browser-check", // https://source.chromium.org/search?q=lang:cpp+symbol:kNoDefaultBrowserCheck&ss=chromium
|
||||
"--no-pings", // https://source.chromium.org/search?q=lang:cpp+symbol:kNoPings&ss=chromium
|
||||
"--single-process", // Needs to be single-process to avoid `prctl(PR_SET_NO_NEW_PRIVS) failed` error
|
||||
"--font-render-hinting=none", // https://github.com/puppeteer/puppeteer/issues/2410#issuecomment-560573612
|
||||
];
|
||||
const chromiumDisableFeatures = [
|
||||
"AudioServiceOutOfProcess",
|
||||
"IsolateOrigins",
|
||||
"site-per-process",
|
||||
];
|
||||
const chromiumEnableFeatures = ["SharedArrayBuffer"];
|
||||
|
||||
const graphicsFlags = [
|
||||
"--hide-scrollbars", // https://source.chromium.org/search?q=lang:cpp+symbol:kHideScrollbars&ss=chromium
|
||||
"--ignore-gpu-blocklist", // https://source.chromium.org/search?q=lang:cpp+symbol:kIgnoreGpuBlocklist&ss=chromium
|
||||
"--in-process-gpu", // https://source.chromium.org/search?q=lang:cpp+symbol:kInProcessGPU&ss=chromium
|
||||
"--window-size=1920,1080", // https://source.chromium.org/search?q=lang:cpp+symbol:kWindowSize&ss=chromium
|
||||
];
|
||||
|
||||
if (Chromium.headless === true) {
|
||||
result.push('--single-process'); // https://source.chromium.org/search?q=lang:cpp+symbol:kSingleProcess&ss=chromium
|
||||
} else {
|
||||
result.push('--start-maximized'); // https://source.chromium.org/search?q=lang:cpp+symbol:kStartMaximized&ss=chromium
|
||||
}
|
||||
// https://chromium.googlesource.com/chromium/src/+/main/docs/gpu/swiftshader.md
|
||||
// Blocked by https://github.com/Sparticuz/chromium/issues/247
|
||||
//this.graphics
|
||||
// ? graphicsFlags.push("--use-gl=angle", "--use-angle=swiftshader")
|
||||
// : graphicsFlags.push("--disable-webgl");
|
||||
graphicsFlags.push("--use-gl=angle", "--use-angle=swiftshader");
|
||||
|
||||
return result;
|
||||
const insecureFlags = [
|
||||
"--allow-running-insecure-content", // https://source.chromium.org/search?q=lang:cpp+symbol:kAllowRunningInsecureContent&ss=chromium
|
||||
"--disable-setuid-sandbox", // https://source.chromium.org/search?q=lang:cpp+symbol:kDisableSetuidSandbox&ss=chromium
|
||||
"--disable-site-isolation-trials", // https://source.chromium.org/search?q=lang:cpp+symbol:kDisableSiteIsolation&ss=chromium
|
||||
"--disable-web-security", // https://source.chromium.org/search?q=lang:cpp+symbol:kDisableWebSecurity&ss=chromium
|
||||
"--no-sandbox", // https://source.chromium.org/search?q=lang:cpp+symbol:kNoSandbox&ss=chromium
|
||||
"--no-zygote", // https://source.chromium.org/search?q=lang:cpp+symbol:kNoZygote&ss=chromium
|
||||
];
|
||||
|
||||
const headlessFlags = [
|
||||
this.headless === "shell" ? "--headless='shell'" : "--headless",
|
||||
];
|
||||
|
||||
return [
|
||||
...puppeteerFlags,
|
||||
...chromiumFlags,
|
||||
`--disable-features=${[
|
||||
...puppeteerDisableFeatures,
|
||||
...chromiumDisableFeatures,
|
||||
].join(",")}`,
|
||||
`--enable-features=${[
|
||||
...puppeteerEnableFeatures,
|
||||
...chromiumEnableFeatures,
|
||||
].join(",")}`,
|
||||
...graphicsFlags,
|
||||
...insecureFlags,
|
||||
...headlessFlags,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns sensible default viewport settings.
|
||||
* Returns sensible default viewport settings for serverless environments.
|
||||
*/
|
||||
static get defaultViewport(): Required<Viewport> {
|
||||
return {
|
||||
|
|
@ -176,57 +291,120 @@ class Chromium {
|
|||
}
|
||||
|
||||
/**
|
||||
* Inflates the current version of Chromium and returns the path to the binary.
|
||||
* If not running on AWS Lambda nor Google Cloud Functions, `null` is returned instead.
|
||||
* Inflates the included version of Chromium
|
||||
* @param input The location of the `bin` folder
|
||||
* @returns The path to the `chromium` binary
|
||||
*/
|
||||
static get executablePath(): Promise<string> {
|
||||
if (Chromium.headless !== true) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
if (existsSync('/tmp/chromium') === true) {
|
||||
for (const file of readdirSync('/tmp')) {
|
||||
if (file.startsWith('core.chromium') === true) {
|
||||
unlinkSync(`/tmp/${file}`);
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.resolve('/tmp/chromium');
|
||||
}
|
||||
|
||||
const input = join(__dirname, '..', 'bin');
|
||||
const promises = [
|
||||
LambdaFS.inflate(`${input}/chromium.br`),
|
||||
LambdaFS.inflate(`${input}/swiftshader.tar.br`),
|
||||
];
|
||||
|
||||
if (/^AWS_Lambda_nodejs(?:10|12|14|16)[.]x$/.test(process.env.AWS_EXECUTION_ENV) === true) {
|
||||
promises.push(LambdaFS.inflate(`${input}/aws.tar.br`));
|
||||
}
|
||||
|
||||
return Promise.all(promises).then((result) => result.shift());
|
||||
static async executablePath(input?: string): Promise<string> {
|
||||
/**
|
||||
* If the `chromium` binary already exists in /tmp/chromium, return it.
|
||||
*/
|
||||
if (existsSync("/tmp/chromium") === true) {
|
||||
return Promise.resolve("/tmp/chromium");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean indicating if we are running on AWS Lambda or Google Cloud Functions.
|
||||
* True is returned if the NODE_ENV is set to 'test' for easier integration testing.
|
||||
* False is returned if Serverless environment variables `IS_LOCAL` or `IS_OFFLINE` are set.
|
||||
* If input is a valid URL, download and extract the file. It will extract to /tmp/chromium-pack
|
||||
* and executablePath will be recursively called on that location, which will then extract
|
||||
* the brotli files to the correct locations
|
||||
*/
|
||||
static get headless() {
|
||||
if (process.env.IS_LOCAL !== undefined || process.env.IS_OFFLINE !== undefined) {
|
||||
return false;
|
||||
if (input && isValidUrl(input)) {
|
||||
return this.executablePath(await downloadAndExtract(input));
|
||||
}
|
||||
if (process.env.NODE_ENV === "test") {
|
||||
return true;
|
||||
}
|
||||
const environments = [
|
||||
'AWS_LAMBDA_FUNCTION_NAME',
|
||||
'FUNCTION_NAME',
|
||||
'FUNCTION_TARGET',
|
||||
'FUNCTIONS_EMULATOR',
|
||||
];
|
||||
|
||||
return environments.some((key) => process.env[key] !== undefined);
|
||||
/**
|
||||
* If input is defined, use that as the location of the brotli files,
|
||||
* otherwise, the default location is ../bin.
|
||||
* A custom location is needed for workflows that using custom packaging.
|
||||
*/
|
||||
input ??= join(__dirname, "..", "bin");
|
||||
|
||||
/**
|
||||
* If the input directory doesn't exist, throw an error.
|
||||
*/
|
||||
if (!existsSync(input)) {
|
||||
throw new Error(`The input directory "${input}" does not exist.`);
|
||||
}
|
||||
|
||||
// Extract the required files
|
||||
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}/al2.tar.br`));
|
||||
}
|
||||
if (isRunningInAwsLambdaNode20()) {
|
||||
promises.push(LambdaFS.inflate(`${input}/al2023.tar.br`));
|
||||
}
|
||||
|
||||
// Await all extractions
|
||||
const result = await Promise.all(promises);
|
||||
// Returns the first result of the promise, which is the location of the `chromium` binary
|
||||
return result.shift() as string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the headless mode.
|
||||
* "shell" means the 'old' (legacy, chromium < 112) headless mode.
|
||||
* `true` means the 'new' headless mode.
|
||||
* https://developer.chrome.com/articles/new-headless/#try-out-the-new-headless
|
||||
* @returns true | "shell"
|
||||
*/
|
||||
public static get headless() {
|
||||
return this.headlessMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the headless mode.
|
||||
* "shell" means the 'old' (legacy, chromium < 112) headless mode.
|
||||
* `true` means the 'new' headless mode.
|
||||
* https://developer.chrome.com/articles/new-headless/#try-out-the-new-headless
|
||||
* @default "shell"
|
||||
*/
|
||||
public static set setHeadlessMode(value: true | "shell") {
|
||||
if (
|
||||
(typeof value === "string" && value !== "shell") ||
|
||||
(typeof value === "boolean" && value !== true)
|
||||
) {
|
||||
throw new Error(
|
||||
`Headless mode must be either \`true\` or 'shell', you entered '${value}'`
|
||||
);
|
||||
}
|
||||
this.headlessMode = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the graphics stack is enabled or disabled
|
||||
* @returns boolean
|
||||
*/
|
||||
public static get graphics() {
|
||||
return this.graphicsMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the graphics stack is enabled or disabled.
|
||||
* @param true means the stack is enabled. WebGL will work.
|
||||
* @param false means that the stack is disabled. WebGL will not work.
|
||||
* `false` will also skip the extract of the graphics driver, saving about a second during initial extract
|
||||
* @default true
|
||||
*/
|
||||
public static set setGraphicsMode(value: boolean) {
|
||||
if (typeof value !== "boolean") {
|
||||
throw new Error(
|
||||
`Graphics mode must be a boolean, you entered '${value}'`
|
||||
);
|
||||
}
|
||||
|
||||
// Disabling 'disabling the gpu'
|
||||
// Blocked by https://github.com/Sparticuz/chromium/issues/247
|
||||
// this.graphicsMode = value;
|
||||
this.graphicsMode = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { createReadStream, createWriteStream, existsSync } from 'fs';
|
||||
import { tmpdir } from 'os';
|
||||
import { basename, join } from 'path';
|
||||
import { extract } from 'tar-fs';
|
||||
import { createBrotliDecompress, createUnzip } from 'zlib';
|
||||
import { createReadStream, createWriteStream, existsSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { basename, join } from "node:path";
|
||||
import { extract } from "tar-fs";
|
||||
import { createBrotliDecompress, createUnzip } from "node:zlib";
|
||||
|
||||
class LambdaFS {
|
||||
/**
|
||||
|
|
@ -11,7 +11,15 @@ class LambdaFS {
|
|||
* @param filePath Path of the file to decompress.
|
||||
*/
|
||||
static inflate(filePath: string): Promise<string> {
|
||||
const output = filePath.includes("swiftshader") ? tmpdir() : join(tmpdir(), basename(filePath).replace(/[.](?:t(?:ar(?:[.](?:br|gz))?|br|gz)|br|gz)$/i, ''));
|
||||
const output = filePath.includes("swiftshader")
|
||||
? tmpdir()
|
||||
: join(
|
||||
tmpdir(),
|
||||
basename(filePath).replace(
|
||||
/[.](?:t(?:ar(?:[.](?:br|gz))?|br|gz)|br|gz)$/i,
|
||||
""
|
||||
)
|
||||
);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (filePath.includes("swiftshader")) {
|
||||
|
|
@ -30,27 +38,33 @@ class LambdaFS {
|
|||
if (/[.](?:t(?:ar(?:[.](?:br|gz))?|br|gz))$/i.test(filePath) === true) {
|
||||
target = extract(output);
|
||||
|
||||
target.once('finish', () => {
|
||||
target.once("finish", () => {
|
||||
return resolve(output);
|
||||
});
|
||||
} else {
|
||||
target = createWriteStream(output, { mode: 0o700 });
|
||||
}
|
||||
|
||||
source.once('error', (error: Error) => {
|
||||
source.once("error", (error: Error) => {
|
||||
return reject(error);
|
||||
});
|
||||
|
||||
target.once('error', (error: Error) => {
|
||||
target.once("error", (error: Error) => {
|
||||
return reject(error);
|
||||
});
|
||||
|
||||
target.once('close', () => {
|
||||
target.once("close", () => {
|
||||
return resolve(output);
|
||||
});
|
||||
|
||||
if (/(?:br|gz)$/i.test(filePath) === true) {
|
||||
source.pipe(/br$/i.test(filePath) ? createBrotliDecompress({ chunkSize: 2 ** 21 }) : createUnzip({ chunkSize: 2 ** 21 })).pipe(target);
|
||||
source
|
||||
.pipe(
|
||||
/br$/i.test(filePath)
|
||||
? createBrotliDecompress({ chunkSize: 2 ** 21 })
|
||||
: createUnzip({ chunkSize: 2 ** 21 })
|
||||
)
|
||||
.pipe(target);
|
||||
} else {
|
||||
source.pipe(target);
|
||||
}
|
||||
|
|
@ -58,4 +72,4 @@ class LambdaFS {
|
|||
}
|
||||
}
|
||||
|
||||
export = LambdaFS;
|
||||
export default LambdaFS;
|
||||
|
|
|
|||
|
|
@ -1,41 +1,11 @@
|
|||
{
|
||||
"compileOnSave": false,
|
||||
"extends": ["@tsconfig/node20/tsconfig", "@tsconfig/strictest"],
|
||||
"compilerOptions": {
|
||||
"alwaysStrict": true,
|
||||
"declaration": true,
|
||||
"declarationDir": "build",
|
||||
"emitDecoratorMetadata": true,
|
||||
"esModuleInterop": true,
|
||||
"experimentalDecorators": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"importHelpers": false,
|
||||
"inlineSourceMap": false,
|
||||
"lib": ["dom", "es2020"],
|
||||
"listEmittedFiles": false,
|
||||
"listFiles": false,
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"outDir": "build",
|
||||
"pretty": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"strictFunctionTypes": true,
|
||||
"strictNullChecks": false,
|
||||
"target": "es2020",
|
||||
"traceResolution": false,
|
||||
"types": ["node"]
|
||||
"lib": ["dom", "ES2023"],
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"outDir": "build"
|
||||
},
|
||||
"exclude": ["build", "node_modules", "tmp"],
|
||||
"include": ["source"],
|
||||
"typeAcquisition": {
|
||||
"enable": true
|
||||
}
|
||||
"include": ["source"]
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue