gpt4 book ai didi

javascript - 如何将 Node js native 模块注入(inject) puppeteer 页面

转载 作者:行者123 更新时间:2023-11-30 06:12:55 24 4
gpt4 key购买 nike

我有一个使用 NWjs 的应用程序,在我的应用程序页面中,它使用了很多很多 nodejs 原生模块(如 fs/http/etc)

然后我想用puppeteer来测试我的页面,所以我们需要注入(inject)nodejs原生模块来运行页面

我尝试在下面的代码中运行,但它无法将 nodejs native 模块注入(inject)页面

const fs = require("fs");
const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
const page = await browser.newPage();
page.on('console', msg => console.log(msg.text()));
await page.exposeFunction("require", function (name) {
console.log("require module name:"+name);
return require(name) // or return fs , result is same
})
await page.evaluate(async () => {

const fs = await window.require("fs");
console.log(fs,typeof fs.readFile);//fs.readFile is undefined

});
await browser.close();
});

最佳答案

您的代码没问题。问题是 puppeteer 只能与页面上下文交换可序列化的数据。也就是说,可通过 JSON.stringify 传输的对象。

函数和其他复杂的 Web Api 不可转移。这就是您在页面上下文中看到 JSHandle@object 的原因。它是一个对象,包含来自 fs 模块的所有 module.exports 可序列化值。

你可以做一个简单的测试看看。在与您的代码相同的文件夹中设置另一个包含简单模块的文件,并尝试在您的代码中要求它。示例:

// file mod1.js
module.exports = {
number: 1,
string: 'test',
object: { complex: 'object' },
function: function() {}, // this will not be transfered
fs: require('fs')
};

现在你运行你的代码调用这个模块:

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
const page = await browser.newPage();
page.on('console', msg => console.log(msg.text()));
await page.exposeFunction("require", function (name) {
console.log("required module name: " + name);
return require(name); // or return fs , result is same
});

await page.evaluate(async () => {
const module = await window.require("./mod1");
// changed to JSON.stringify for you to see module's content
console.log('module:', JSON.stringify(module, null, 2));
});
await browser.close();
});

不幸的是,关于 page.exposeFunction 方法的这一点,文档并不清楚。

编辑:我想出了一个可能的解决方案来要求一个本地模块。我只测试了 fs.unlikSync、fs.writeFileSync 和 fs.readFileSync 方法,但它们都有效。 :) 这是代码:

const puppeteer = require('puppeteer');

// expose every methods of the moduleName to the Page, under window[moduleName] object.
async function exposeModuleMethods(page, moduleName) {
const module = require(moduleName);
const methodsNames = Object.getOwnPropertyNames(module);
for (const methodName of methodsNames) {
await page.exposeFunction('__' + moduleName + '_' + methodName, module[methodName]);
await page.evaluate((moduleName, methodName) => {
window[moduleName] = window[moduleName] || {};
window[moduleName][methodName] = window['__' + moduleName + '_' + methodName]; // alias
}, moduleName, methodName);
}
}

(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
page.on('console', msg => console.log(msg.text()));

// expose `require` on Page. When it is used on Page, the function `exposeModuleMethods`
// expose the individual module's methods on window[moduleName].
await page.exposeFunction('require', async function (moduleName) {
await exposeModuleMethods(page, moduleName);
});

// make the Page require "fs" native module
await page.evaluate(async (moduleName) => await require(moduleName), 'fs');

// make the Page test the "fs" module
await page.evaluate(async (moduleName) => {
// save a file on the current directory named "mod2.js"
await window[moduleName]['writeFileSync']('./mod2.js', 'any text');
// read the file "mod2.js"
const mod2 = await window[moduleName]['readFileSync']('./mod2.js', { encoding: 'utf8' });
// log it's content
console.log(JSON.stringify(mod2, null, 2));
// delete the file
await window[moduleName]['unlinkSync']('./mod2.js');
}, 'fs');

await browser.close();
})();

关于javascript - 如何将 Node js native 模块注入(inject) puppeteer 页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57863547/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com