Consider puppeteer's launch()
method. The usage guidelines in the Puppeteer readme recommend to use const puppeteer = require('puppeteer')
and then puppeteer.launch()
:
const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://example.com'); await page.screenshot({path: 'example.png'}); await browser.close(); })();
And Puppeteer itself exports an instance, which seems to further confirm the default export is meant to be used:
module.exports = new Puppeteer(__dirname, preferredRevision, isPuppeteerCore);
However, the Flow type definitions for puppeteer ≥1.12 use declare export function launch()
and don't include a default export, so Flow requires me to write import { launch } from "puppeteer"
instead of import puppeteer from "puppeteer"
.
But using the named import yields TypeError: Cannot read property '_launcher' of undefined
. Similarly, we can confirm this doesn't work with a simple test (Node v10.15.0, puppeteer 1.19.0):
const puppeteer = require("puppeteer");
puppeteer.launch(); // works
const { launch } = require("puppeteer");
launch(); // TypeError: Cannot read property '_launcher' of undefined
(Presumably this is because const { launch } =
gives me an unbound method — this === undefined
when called.)
Attempt 2: In Flow you can also use a namespaced import import * as puppeteer from "puppeteer"
, but it seems this explicitly forgoes access to the default export, instead yielding TypeError: puppeteer.launch is not a function
.
(I'm less familiar with TypeScript, but the DefinitelyTyped defs for Puppeteer also use export function launch()
rather than a default export. That said, they seem intended to be used with import * as puppeteer from "puppeteer"
, although I'm not sure why this would work when it doesn't in Flow; perhaps a difference in how TypeScript handles ES6 modules?)
So, am I holding it wrong, or are the Flow type definitions wrong? (In which case, how has nobody else encountered this problem?)