puppeteer
puppeteer copied to clipboard
[Bug]: crash on PDF render
Bug description
Steps to reproduce the problem:
- clone https://github.com/VagrantAI-c/Puppeteer-pdf-render-repro
- run
npm ci - run
npm run build - run
npm run serve
Reproduce from scratch:
import { launch } from 'puppeteer';
(async () => {
const browser = await launch({
headless: true,
args: [
'--disable-gpu',
'--disable-dev-shm-usage',
'--disable-setuid-sandbox',
'--no-sandbox',
],
});
const page = await browser.newPage();
const content = '<!doctype html><html lang="en"><head></head><body><h1>Test</h1></body></html>';
await page.setContent(content, { waitUntil: 'networkidle0' });
await page.pdf({ format: 'a4' });
await page.close();
})();
This error is happening on https://github.com/puppeteer/puppeteer/blob/ce0dd25349b3141409cf68121a2bf9a770d9ecf7/src/common/util.ts#L387 while running await page.pdf({ format: 'a4' });
Puppeteer version
14.4.0
Node.js version
18.3.0
npm version
8.11.0
What operating system are you seeing the problem on?
Windows
Relevant log output
\dist\main.js:3113
return new Readable({
^
TypeError: Readable is not a constructor
at Object.getReadableFromProtocolStream (\dist\main.js:3113:12)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Page.pdf (\dist\main.js:6019:26)
at async \dist\main.js:35011:5
I am not sure exactly why but webpack does not seem to process the dynamic import correctly. Instead of returning the default export, it returns an object that includes {default: StreamModule}. I am not very familiar with webpack but perhaps it could be solved by fixing the configuration?
It also might be involved with Typescript configuration. I don't know if there's a correct or incorrect config: Puppeteer doesn't provide working solutions and examples with bundlers, so I believe any config should be fine by default. Moreover, this config produces correct and working output at [email protected]
Yeah, we don't officially support bundlers (e.g., we don't run tests with them) but we also try to fix issues whenever possible. We made changes to TypeScript configs to support ESM alongside CJS so perhaps it caused it but it's hard to say where exactly the problem is. Which build output (esm or cjs) does webpack use in your example?
I don't know exactly, but I tried some experiments on Typescript module option: changing it from es2022 to nodenext/node16 helps, but I can't tell exactly why.
perhaps @jrandolf has an idea! Great that there is a workaround.
I am seeing this same error in version 14.4.1; downgrading to 13.7.0 resolved it for me.
I am having the same issue.
I have also run into this issue. It occurs when webpack (v5 on my end) bundles puppeteer. I have solved it by explicitly declaring webpack ignore directive when importing a file which uses puppeteer. I did this via dynamic es import, but a static one could be done in a very similar way:
const loadModule = async (modulePath) => {
try {
return await import(/* webpackIgnore: true */ modulePath)
} catch (e) {
throw new ImportError(`Unable to import module ${modulePath}`)
}
}
const renderPdf = (await loadModule('../../renderPdf/index.js')).default
This is not an issue with puppeteer at all, but with webpack by itself.
A fresh minimal webpack repo with the following code also throws for the same reason:
async function handler() {
const { Readable } = await import('node:stream');
assert(typeof Readable !== 'undefined', 'Readable is undefined.');
}
void handler();
See: https://github.com/webpack/webpack/issues/16757
Definitely a webpack problem, not a puppeteer one.
Moved my bundling to esbuild and it worked first time.
Closing based on previous comments
I was able to work around this by using createRequire to load the cjs output instead of esm.
Change this import:
import puppeteer from 'puppeteer-core'
to this:
import { createRequire } from 'module'
const require = createRequire(import.meta.url)
const puppeteer = require('puppeteer-core')
I'm guessing this has to do with using "type": "module" in my package.json file and "moduleResolution": "nodenext" in my tsconfig.json file. I've run into a handful of similar issues with other libraries, like https://github.com/vercel/next.js/issues/46078
-
TL;DR
const puppeteer = require('puppeteer'); -
Reference https://github.com/webpack/webpack/issues/16757#issuecomment-1851590537