如何将所需模块对象传入Puppeteer的page.evaluate?遇引用错误
解决Puppeteer page.evaluate传入模块对象时的ReferenceError问题
嘿,我之前也踩过这个坑!咱们先搞懂为啥会报错:
page.evaluate 里的代码是跑在浏览器的沙箱环境里的,和你的Node.js上下文完全是两个独立的世界。你直接把Node环境里的模块对象传进去,浏览器根本不知道这个对象是什么,自然就抛出 ReferenceError 了。
下面给你几个实用的解决办法,根据你的需求选就行:
1. 传递模块里的可序列化值/纯函数
如果只是需要模块里的某个具体值(比如字符串、数字、普通对象),或者不依赖Node API的纯函数,你可以把它们单独提取出来,作为参数传给 page.evaluate——只有可JSON序列化的内容才能在两个上下文之间传递。
举个例子:
// 引入模块 const myToolModule = require('./my-tool-module'); // 提取模块里的可序列化值和纯函数 const configValue = myToolModule.apiKey; const calculateSum = (a, b) => a + b; // 这个函数里不能用Node的API哦 // 传入evaluate执行 await page.evaluate((apiKey, sumFunc) => { console.log('API Key:', apiKey); console.log('Sum result:', sumFunc(3, 5)); }, configValue, calculateSum);
2. 把模块注入到浏览器环境
如果你的模块本身支持在浏览器端运行(比如没有用到fs、path这类Node专属API的工具库),可以用 page.addScriptTag 把模块文件直接注入到浏览器里,之后就能在 evaluate 里直接调用了。
比如:
// 把模块的浏览器兼容版本注入到页面 await page.addScriptTag({ path: './node_modules/lodash/lodash.min.js' }); // 现在就能在浏览器上下文里用lodash了 await page.evaluate(() => { const arr = [1, 2, 3]; const doubledArr = _.map(arr, num => num * 2); console.log(doubledArr); // 输出 [2,4,6] });
额外注意点
- 传给
page.evaluate的函数,内部绝对不能引用Node环境的变量(比如process、require这些),因为函数会被序列化后传到浏览器执行,这些变量在浏览器里根本不存在。 - 你用的Puppeteer 1.0.0和Node.js 8.9.3都是比较老的版本了,虽然这个上下文隔离的机制一直没变,但如果后续有条件,升级到更稳定的新版本会减少很多潜在问题。
内容的提问来源于stack exchange,提问作者Alex K
相关产品推荐
相关产品推荐

