
在 Puppeteer 中,page.$eval() 等 DOM 执行方法运行在浏览器环境(页面上下文)中,无法直接访问 Node.js 主进程中的 const 或 require 变量;必须显式将所需数据作为参数传入。
在 puppeteer 中,`page.$eval()` 等 dom 执行方法运行在浏览器环境(页面上下文)中,无法直接访问 node.js 主进程中的 `const` 或 `require` 变量;必须显式将所需数据作为参数传入。
当你在 main.js 中执行:
await page.$eval('#email', (el) => console.log(SRLoginCredentials));
这段箭头函数实际被序列化后注入并运行在浏览器端的 JavaScript 引擎中——它与 Node.js 主进程完全隔离,既无模块系统,也无法访问 SRLoginCredentials 这样的顶层常量(该变量仅存在于 Node.js 的 V8 上下文中)。因此输出 undefined 是预期行为,而非 Bug。
✅ 正确做法:通过 $eval 的第二个参数(传递给浏览器函数的参数)显式传入数据:
await page.$eval('#email', (el, credentials) => {
console.log(credentials); // ✅ 正确输出 { email: '...', password: '...' }
el.value = credentials.email;
}, SRLoginCredentials); // ← 第三个参数:将 Node.js 变量传入浏览器上下文
⚠️ 注意事项:
- 传入的参数必须是可序列化的值(如 plain object、string、number、boolean、array),不可传入函数、
Date、RegExp、undefined、Symbol或循环引用对象; - 若需复杂逻辑或敏感信息(如密码),避免在前端暴露——应优先使用 Puppeteer 的
page.type()或page.fill()直接操作输入框,而非注入脚本读取凭证; - 不要尝试在浏览器端
require或访问module.exports—— 浏览器无 CommonJS 运行时。
? 补充:更安全的登录示例(不暴露凭证到页面脚本)
await page.type('#email', SRLoginCredentials.email, { delay: 50 });
await page.type('#password', SRLoginCredentials.password, { delay: 50 });
await page.click('#login-btn');
这种方式完全绕过浏览器 JS 上下文,由 Puppeteer 主进程直接驱动 DOM,既安全又可靠。
总结:Node.js 与浏览器上下文是两个独立的 JavaScript 运行时。跨上下文通信必须显式传参,切勿假设变量“自动可见”。理解这一隔离机制,是写出健壮 Puppeteer 自动化脚本的关键基础。











