在windows上测试了我的项目后,我已经将它部署到基于ubuntu的VM上,这就是Puppeteer行为困扰我的地方。我确实安装了所有必需的依赖项,但我有一种感觉,我的错误不一定是由于缺乏依赖而产生的,更多的是关于配置问题。
函数fignature:
async initPuppeteerBrowser() {
if (
this.puppeteerBrowser === null ||
(await this.puppeteerBrowser.pages()).length === 0
) {
this.puppeteerBrowser = await launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] });
}
return await this.puppeteerBrowser.newPage();
}
导致:
err: {
"type": "TypeError",
"message": "Cannot read properties of undefined (reading '_launcher')",
"stack":
TypeError: Cannot read properties of undefined (reading '_launcher')
at launch (/root/dev/logoex-server/node_modules/puppeteer/lib/cjs/puppeteer/node/Puppeteer.js:125:21)
at CorporationsScraper.initPuppeteerBrowser (/root/dev/logoex-server/dist/aid/scraper/corporations.scraper.js:33:66)
at CorporationsScraper.corporationIterator (/root/dev/logoex-server/dist/aid/scraper/corporations.scraper.js:54:37)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
}
我不明白我该如何开始调查这个问题
不确定,如果这对你的情况有帮助-我有Typescript, compilerOptionslib: ["es2020"]
,它抛出了这个错误。将其更改为lib: ["es2017"]
解决了这个问题。我甚至不确定,为什么它会这样影响它。我猜,当你通过导入import { fn } from "somewhere"
得到一个函数,但该函数以某种方式从类实例导出-它失去了它的绑定this
。
否则像这样导入就可以了
// Works
import Puppeteer, { Browser, PDFOptions } from "puppeteer";
browser = await Puppeteer.launch({});
// Doesn't work
import { launch, Browser, PDFOptions } from "puppeteer";
browser = await launch({});
我的解决办法是从使用:
import { launch } from 'puppeteer';
const browser = await launch(...);
import Puppeteer from 'puppeteer';
const browser = await Puppeteer.launch(...);
像这样使用
async initPuppeteerBrowser() {
if (
this.puppeteerBrowser === null ||
(await this.puppeteerBrowser.pages()).length === 0
) {
this.puppeteerBrowser = await launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] });
}
return this.puppeteerBrowser.newPage();
}
我的环境
我正在使用commonjs模块格式运行我的Node.js应用程序。
puppeteer@13.5.1
typescript@4.5.4
node@14.18.3
- 我的
package.json
适当地没有指定"module": true
。 - 虽然我在TypeScript代码中使用ES模块语法,但我将
"module": "commonjs"
设置为编译为commonjs。
我的tsconfig.json
是这样的:
{
"compilerOptions": {
"target": "ESNext",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"module": "commonjs",
"moduleResolution": "Node",
// ... other inconsequential options ...
},
}
<标题>失败的方法我用上面的tsconfig.json
在官方的TypeScript平台上进行了测试,以分析这些不同的方法转换成什么。
方法1
来源import { launch } from 'puppeteer';
launch();
输出const puppeteer_1 = require("puppeteer");
(0, puppeteer_1.launch)();
方法2
来源import { default as puppeteer } from 'puppeteer';
puppeteer.launch();
输出var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const puppeteer_1 = __importDefault(require("puppeteer"));
puppeteer_1.default.launch();
3
方法来源import * as puppeteer from 'puppeteer';
puppeteer.launch();
输出var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const puppeteer = __importStar(require("puppeteer"));
puppeteer.launch();
<标题>工作方法…最后,我尝试了TypeScript特殊的import = require()
格式。
import puppeteer = require("puppeteer");
puppeteer.launch();
输出const puppeteer = require("puppeteer");
puppeteer.launch();
这看起来和方法1最相似。我真的不确定什么魔法方法1与它的0
参数执行,但也许它正在擦除this
上下文或其他东西,这就是导致模块无法找到其launch
属性的原因(它可能通过this.launch
引用)?只是猜测。