Firebase Functions中Async/Await使用异常:部署后返回空响应
Firebase Functions部署后Puppeteer接口返回空响应,本地调试正常
问题描述
在Firebase Functions中使用Async/Await结合Puppeteer编写网页抓取接口,本地通过firebase serve测试可正常返回渲染后的HTML,但部署到线上后接口仅返回空响应{}。此外,预部署时ESLint触发Parsing error: Unexpected token function错误,移除firebase.json中的predeploy lint配置后部署成功,但线上接口异常。
代码示例
const functions = require("firebase-functions"); const puppeteer = require('puppeteer'); async function getHtml(url) { const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox',] }); const page = await browser.newPage(); await page.goto(url, { waitUntil: ['networkidle0', 'networkidle2', 'load', 'domcontentloaded'] }); const k = await page.content() await browser.close(); return k }; exports.api = functions.runWith({ memory: '512MB' }) .https.onRequest((request, response) => { functions.logger.info("Hello logs!", { structuredData: true }); getHtml(request.query.url) .then(function (res) { response.send(res); console.log(res) }) .catch(function (err) { response.send(err); }) });
复现步骤
- 执行
firebase init,选择Functions、JavaScript(可关闭ESLint); - 安装puppeteer:
npm install puppeteer; - 将上述代码粘贴到
/functions/index.js; - 本地执行
firebase serve,测试带url参数的接口,可正常返回渲染后的HTML; - 执行
firebase deploy后,访问线上接口并添加url参数,仅返回{}。
解决方案
1. 修复ESLint语法错误(可选,推荐保留lint)
若需保留预部署的ESLint检查,修改functions/.eslintrc.js中的parserOptions.ecmaVersion为2017或更高版本,以支持async/await语法:
module.exports = { root: true, env: { es6: true, node: true, }, parserOptions: { ecmaVersion: 2017, // 或更高版本如2020 }, rules: { // 保留原有规则或按需调整 }, };
2. 适配Puppeteer在Firebase云环境运行
Firebase Functions的Linux环境与本地存在差异,默认puppeteer包可能无法正常运行,改用puppeteer-core配合chrome-aws-lambda:
- 卸载原puppeteer:
npm uninstall puppeteer
- 安装适配包:
npm install puppeteer-core chrome-aws-lambda
- 修改
getHtml函数代码:
const chromium = require('chrome-aws-lambda'); const puppeteer = require('puppeteer-core'); async function getHtml(url) { const browser = await puppeteer.launch({ args: chromium.args, defaultViewport: chromium.defaultViewport, executablePath: await chromium.executablePath, headless: chromium.headless, }); const page = await browser.newPage(); // 简化waitUntil参数,避免不必要的等待超时 await page.goto(url, { waitUntil: ['networkidle2', 'domcontentloaded'] }); const html = await page.content(); await browser.close(); return html; };
3. 调整函数资源配置
Puppeteer运行Chrome需要足够内存和超时时间,修改函数配置:
exports.api = functions.runWith({ memory: '1GB', // 至少1GB,可按需调整至2GB timeoutSeconds: 90 // 延长超时时间,最大支持540秒 }) .https.onRequest(async (request, response) => { functions.logger.info("Request received", { url: request.query.url }); try { const url = request.query.url; // 校验参数是否存在 if (!url) { response.status(400).send("Missing 'url' query parameter"); return; } const html = await getHtml(url); response.send(html); functions.logger.info("HTML fetched successfully"); } catch (err) { // 记录详细错误日志到Firebase控制台 functions.logger.error("Fetch failed", { error: err.message, url: request.query.url }); response.status(500).send(`Error: ${err.message}`); } });
4. 指定Node.js版本
在functions/package.json中明确指定与本地一致的Node.js版本(Firebase支持14/16/18/20版本):
{ "engines": { "node": "18" } }
5. 排查线上日志
登录Firebase控制台,进入Functions的日志页面,查看具体错误信息(如Chrome启动失败、页面加载超时、参数异常等),辅助定位问题。
内容的提问来源于stack exchange,提问作者Vayun
相关产品推荐
相关产品推荐

