提问人:Igor Savinkin 提问时间:4/14/2023 最后编辑:Igor Savinkin 更新时间:4/14/2023 访问量:219
Netlify 云部署 - 无法获取浏览器启动的 chromium.executablePath
Netlify cloud deploy - failure to get chromium.executablePath for browser launch
问:
我在 Netlify 上做了一个无服务器函数。这是 Puppeteer 的简单浏览器自动化功能:
const chromium = require("@sparticuz/chromium");
const puppeteer = require('puppeteer-core');
chromium.setHeadlessMode = true;
chromium.setGraphicsMode = false;
exports.handler = async function (event, context) {
const browser = await puppeteer.launch({
args: chromium.args,
defaultViewport: chromium.defaultViewport,
executablePath: process.env.CHROME_EXECUTABLE_PATH || await
chromium.executablePath,
headless: chromium.headless,
});
await browser.close();
return {
statusCode: 200,
body: JSON.stringify({
status: "The 'Element' function works!"
})
};
}
该函数在本地环境中相当有效。然而,当部署到 Netlify 时,它会返回以下错误:
此函数已崩溃
函数代码中未处理的错误触发了以下消息:
TypeError - “file”参数的类型必须为 string。接收函数 executablePath
Stack trace
TypeError [ERR_INVALID_ARG_TYPE]: The "file" argument must be of type string. Received function executablePath
at new NodeError (node:internal/errors:387:5)
at validateString (node:internal/validators:162:11)
at normalizeSpawnArguments (node:child_process:528:3)
at Object.spawn (node:child_process:726:13)
at new Process (/var/task/node_modules/@puppeteer/browsers/lib/cjs/launch.js:143:87)
at launch (/var/task/node_modules/@puppeteer/browsers/lib/cjs/launch.js:80:12)
at ChromeLauncher.launch (/var/task/node_modules/puppeteer-core/lib/cjs/puppeteer/node/ProductLauncher.js:90:54)
at async Runtime.exports.handler (/var/task/functions/element.js:11:21)
在我看来,云服务器无法获取浏览器启动的chromium.executablePath。
更新
在我输出const executablePath = await chromium.executablePath;
我得到了以下信息:
async executablePath(input) {
/**
* If the `chromium` binary already exists in /tmp/chromium, return it.
*/
if ((0, node_fs_1.existsSync)("/tmp/chromium") === true) {
return Promise.resolve("/tmp/chromium");
}
/**
* 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
*/
if (input && (0, helper_1.isValidUrl)(input)) {
return this.executablePath(await(0, helper_1.downloadAndExtract)(input));
}
/**
* 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 ?? (input = (0, node_path_1.join)(__dirname, "..", "bin"));
/**
* If the input directory doesn't exist, throw an error.
*/
if (!(0, node_fs_1.existsSync)(input)) {
throw new Error(`The input directory "${input}" does not exist.`);
}
// Extract the required files
const promises = [lambdafs_1.default.inflate(`${input}/chromium.br`)];
if (this.graphics) {
// Only inflate graphics stack if needed promises.push(lambdafs_1.default.inflate(`${input}/swiftshader.tar.br`));
}
if ((0, helper_1.isRunningInAwsLambda)()) {
// If running in AWS Lambda, extract more required files
promises.push(lambdafs_1.default.inflate(`${input}/aws.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();
}
这是否意味着无论什么都无法解决?await chromium.executablePath
await
答:
0赞
Igor Savinkin
4/14/2023
#1
我的错字。应该有:
await chromium.executablePath();
而不是:
await chromium.executablePath;
评论