refactor!: enable the new-headless mode by default (#11815)

This commit is contained in:
Alex Rudenko 2024-02-02 13:25:43 +01:00 committed by GitHub
parent 7564dfa911
commit 75c9e117f1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 85 additions and 92 deletions

View File

@ -19,7 +19,7 @@ jobs:
suite:
- chrome-headless
- chrome-headful
- chrome-new-headless
- chrome-headless-shell
- chrome-bidi
os:
- ubuntu-latest

View File

@ -154,7 +154,7 @@ jobs:
suite:
- chrome-headless
- chrome-headful
- chrome-new-headless
- chrome-headless-shell
- chrome-bidi
os:
- ubuntu-latest

View File

@ -21,7 +21,7 @@ on:
options:
- chrome-headless
- chrome-headful
- chrome-new-headless
- chrome-headless-shell
- chrome-bidi
- firefox-headful
- firefox-headless

View File

@ -11,7 +11,7 @@
"options": [
"chrome-headless",
"chrome-headful",
"chrome-new-headless",
"chrome-headless-shell",
"firefox-headless",
"firefox-headful",
"firefox-bidi",

View File

@ -181,7 +181,7 @@ import puppeteer from 'puppeteer';
**1. Uses Headless mode**
By default Puppeteer launches Chrome in
[old Headless mode](https://developer.chrome.com/articles/new-headless/).
[the Headless mode](https://developer.chrome.com/articles/new-headless/).
```ts
const browser = await puppeteer.launch();
@ -189,12 +189,16 @@ const browser = await puppeteer.launch();
const browser = await puppeteer.launch({headless: true});
```
[Chrome 112 launched a new Headless mode](https://developer.chrome.com/articles/new-headless/) that might cause some differences in behavior compared to the old Headless implementation.
In the future Puppeteer will start defaulting to new implementation.
We recommend you try it out before the switch:
Before v22, Puppeteer launched the [old Headless mode](https://developer.chrome.com/articles/new-headless/) by default.
The old headless mode is now known as
[`chrome-headless-shell`](https://developer.chrome.com/blog/chrome-headless-shell)
and ships as a separate binary. `chrome-headless-shell` does not match the
behavior of the regular Chrome completely but it is currently more performant
for automation tasks where the complete Chrome feature set is not needed. If the performance
is more important for your use case, switch to `chrome-headless-shell` as following:
```ts
const browser = await puppeteer.launch({headless: 'new'});
const browser = await puppeteer.launch({headless: 'shell'});
```
To launch a "headful" version of Chrome, set the

View File

@ -14,10 +14,10 @@ export interface BrowserLaunchArgumentOptions
## Properties
| Property | Modifiers | Type | Description | Default |
| ------------- | --------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| args | <code>optional</code> | string\[\] | Additional command line arguments to pass to the browser instance. | |
| debuggingPort | <code>optional</code> | number | Specify the debugging port number to use | |
| devtools | <code>optional</code> | boolean | Whether to auto-open a DevTools panel for each tab. If this is set to <code>true</code>, then <code>headless</code> will be forced to <code>false</code>. | <code>false</code> |
| headless | <code>optional</code> | boolean \| 'new' | Whether to run the browser in headless mode. | <code>true</code> |
| userDataDir | <code>optional</code> | string | Path to a user data directory. [see the Chromium docs](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/user_data_dir.md) for more info. | |
| Property | Modifiers | Type | Description | Default |
| ------------- | --------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| args | <code>optional</code> | string\[\] | Additional command line arguments to pass to the browser instance. | |
| debuggingPort | <code>optional</code> | number | Specify the debugging port number to use | |
| devtools | <code>optional</code> | boolean | Whether to auto-open a DevTools panel for each tab. If this is set to <code>true</code>, then <code>headless</code> will be forced to <code>false</code>. | <code>false</code> |
| headless | <code>optional</code> | boolean \| 'shell' | Whether to run the browser in headless mode. | <code>true</code> |
| userDataDir | <code>optional</code> | string | Path to a user data directory. [see the Chromium docs](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/user_data_dir.md) for more info. | |

View File

@ -181,7 +181,7 @@ import puppeteer from 'puppeteer';
**1. Uses Headless mode**
By default Puppeteer launches Chrome in
[old Headless mode](https://developer.chrome.com/articles/new-headless/).
[the Headless mode](https://developer.chrome.com/articles/new-headless/).
```ts
const browser = await puppeteer.launch();
@ -189,12 +189,16 @@ const browser = await puppeteer.launch();
const browser = await puppeteer.launch({headless: true});
```
[Chrome 112 launched a new Headless mode](https://developer.chrome.com/articles/new-headless/) that might cause some differences in behavior compared to the old Headless implementation.
In the future Puppeteer will start defaulting to new implementation.
We recommend you try it out before the switch:
Before v22, Puppeteer launched the [old Headless mode](https://developer.chrome.com/articles/new-headless/) by default.
The old headless mode is now known as
[`chrome-headless-shell`](https://developer.chrome.com/blog/chrome-headless-shell)
and ships as a separate binary. `chrome-headless-shell` does not match the
behavior of the regular Chrome completely but it is currently more performant
for automation tasks where the complete Chrome feature set is not needed. If the performance
is more important for your use case, switch to `chrome-headless-shell` as following:
```ts
const browser = await puppeteer.launch({headless: 'new'});
const browser = await puppeteer.launch({headless: 'shell'});
```
To launch a "headful" version of Chrome, set the

View File

@ -32,7 +32,7 @@
"test:chrome:bidi-local": "wireit",
"test:chrome:headful": "wireit",
"test:chrome:headless": "wireit",
"test:chrome:new-headless": "wireit",
"test:chrome:shell": "wireit",
"test:firefox": "wireit",
"test:firefox:bidi": "wireit",
"test:firefox:bidi:headful": "wireit",
@ -83,7 +83,7 @@
"test:chrome:bidi",
"test:chrome:headful",
"test:chrome:headless",
"test:chrome:new-headless"
"test:chrome:shell"
]
},
"test:chrome:bidi": {
@ -98,8 +98,8 @@
"test:chrome:headless": {
"command": "npm test -- --test-suite chrome-headless"
},
"test:chrome:new-headless": {
"command": "npm test -- --test-suite chrome-new-headless"
"test:chrome:shell": {
"command": "npm test -- --test-suite chrome-headless-shell"
},
"test:firefox:bidi": {
"command": "npm test -- --test-suite firefox-bidi"

View File

@ -167,7 +167,7 @@ export interface PDFOptions {
*
* @remarks
* If this is enabled the PDF will also be tagged (accessible)
* Currently only works in old Headless (headless = true)
* Currently only works in old Headless (headless = 'shell')
* crbug/840455#c47
*
* @defaultValue `false`

View File

@ -36,25 +36,6 @@ export class ChromeLauncher extends ProductLauncher {
}
override launch(options: PuppeteerNodeLaunchOptions = {}): Promise<Browser> {
const headless = options.headless ?? true;
if (
headless === true &&
this.puppeteer.configuration.logLevel === 'warn' &&
!Boolean(process.env['PUPPETEER_DISABLE_HEADLESS_WARNING'])
) {
console.warn(
[
'\x1B[1m\x1B[43m\x1B[30m',
'Puppeteer old Headless deprecation warning:\x1B[0m\x1B[33m',
' In the near future `headless: true` will default to the new Headless mode',
' for Chrome instead of the old Headless implementation. For more',
' information, please see https://developer.chrome.com/articles/new-headless/.',
' Consider opting in early by passing `headless: "new"` to `puppeteer.launch()`',
' If you encounter any bugs, please report them to https://github.com/puppeteer/puppeteer/issues/new/choose.\x1B[0m\n',
].join('\n ')
);
}
if (
this.puppeteer.configuration.logLevel === 'warn' &&
process.platform === 'darwin' &&
@ -254,7 +235,7 @@ export class ChromeLauncher extends ProductLauncher {
}
if (headless) {
chromeArguments.push(
headless === 'new' ? '--headless=new' : '--headless',
headless === true ? '--headless=new' : '--headless',
'--hide-scrollbars',
'--mute-audio'
);
@ -272,7 +253,7 @@ export class ChromeLauncher extends ProductLauncher {
override executablePath(
channel?: ChromeReleaseChannel,
headless?: boolean | 'new'
headless?: boolean | 'shell'
): string {
if (channel) {
return computeSystemExecutablePath({

View File

@ -17,13 +17,18 @@ export interface BrowserLaunchArgumentOptions {
* Whether to run the browser in headless mode.
*
* @remarks
* In the future `headless: true` will be equivalent to `headless: 'new'`.
* You can read more about the change {@link https://developer.chrome.com/articles/new-headless/ | here}.
* Consider opting in early by setting the value to `"new"`.
*
* - `true` launches the browser in the
* {@link https://developer.chrome.com/articles/new-headless/ | new headless}
* mode.
*
* - `'shell'` launches
* {@link https://developer.chrome.com/blog/chrome-headless-shell | shell}
* known as the old headless mode.
*
* @defaultValue `true`
*/
headless?: boolean | 'new';
headless?: boolean | 'shell';
/**
* Path to a user data directory.
* {@link https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/user_data_dir.md | see the Chromium docs}

View File

@ -393,7 +393,7 @@ export abstract class ProductLauncher {
/**
* @internal
*/
protected resolveExecutablePath(headless?: boolean | 'new'): string {
protected resolveExecutablePath(headless?: boolean | 'shell'): string {
let executablePath = this.puppeteer.configuration.executablePath;
if (executablePath) {
if (!existsSync(executablePath)) {
@ -404,10 +404,10 @@ export abstract class ProductLauncher {
return executablePath;
}
function productToBrowser(product?: Product, headless?: boolean | 'new') {
function productToBrowser(product?: Product, headless?: boolean | 'shell') {
switch (product) {
case 'chrome':
if (headless === true) {
if (headless === 'shell') {
return InstalledBrowser.CHROMEHEADLESSSHELL;
}
return InstalledBrowser.CHROME;

View File

@ -338,7 +338,7 @@
{
"testIdPattern": "[autofill.spec] *",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "headless"],
"parameters": ["chrome", "chrome-headless-shell"],
"expectations": ["FAIL"]
},
{
@ -1030,7 +1030,7 @@
{
"testIdPattern": "[prerender.spec] Prerender can screencast",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["new-headless"],
"parameters": ["headless"],
"expectations": ["FAIL", "PASS"]
},
{
@ -1126,13 +1126,13 @@
{
"testIdPattern": "[screenshot.spec] Screenshots Cdp should work in \"fromSurface: false\" mode",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["headless"],
"parameters": ["chrome-headless-shell"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[screenshot.spec] Screenshots Cdp should work in \"fromSurface: false\" mode",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["new-headless"],
"parameters": ["headless"],
"expectations": ["SKIP"]
},
{
@ -2510,13 +2510,13 @@
{
"testIdPattern": "[navigation.spec] navigation Page.goto should work with anchor navigation",
"platforms": ["linux"],
"parameters": ["chrome", "headless"],
"parameters": ["chrome", "chrome-headless-shell"],
"expectations": ["PASS", "TIMEOUT"]
},
{
"testIdPattern": "[navigation.spec] navigation Page.goto should work with anchor navigation",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "headless"],
"parameters": ["chrome", "chrome-headless-shell"],
"expectations": ["PASS", "TIMEOUT"]
},
{
@ -3235,7 +3235,7 @@
{
"testIdPattern": "[pdf.spec] Page.pdf can print to PDF with outline",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "new-headless"],
"parameters": ["chrome", "headless"],
"expectations": ["FAIL"]
},
{
@ -3760,56 +3760,56 @@
{
"testIdPattern": "[CDPSession.spec] Target.createCDPSession should send events",
"platforms": ["win32"],
"parameters": ["cdp", "chrome", "new-headless"],
"parameters": ["cdp", "chrome", "headless"],
"expectations": ["FAIL", "PASS"]
},
{
"testIdPattern": "[chromiumonly.spec] Chromium-Specific Launcher tests Puppeteer.launch |pipe| option should fire \"disconnected\" when closing with pipe",
"platforms": ["darwin"],
"parameters": ["cdp", "chrome", "new-headless"],
"parameters": ["cdp", "chrome", "headless"],
"expectations": ["FAIL"],
"comment": "Remove with M121"
},
{
"testIdPattern": "[devtools.spec] DevTools should expose DevTools as a page",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "chrome", "headless"],
"parameters": ["cdp", "chrome", "chrome-headless-shell"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[devtools.spec] DevTools should open devtools when \"devtools: true\" option is given",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "chrome", "headless"],
"parameters": ["cdp", "chrome", "chrome-headless-shell"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[devtools.spec] DevTools target.page() should return a DevTools page if asPage is used",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "chrome", "headless"],
"parameters": ["cdp", "chrome", "chrome-headless-shell"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[devtools.spec] DevTools target.page() should return a DevTools page if custom isPageTarget is provided",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "chrome", "headless"],
"parameters": ["cdp", "chrome", "chrome-headless-shell"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[extensions.spec] extensions background_page target type should be available",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "chrome", "headless"],
"parameters": ["cdp", "chrome", "chrome-headless-shell"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[extensions.spec] extensions service_worker target type should be available",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "chrome", "headless"],
"parameters": ["cdp", "chrome", "chrome-headless-shell"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[extensions.spec] extensions target.page() should return a background_page",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "chrome", "headless"],
"parameters": ["cdp", "chrome", "chrome-headless-shell"],
"expectations": ["SKIP"]
},
{
@ -3821,7 +3821,7 @@
{
"testIdPattern": "[network.spec] network Network Events Page.Events.Request",
"platforms": ["linux"],
"parameters": ["cdp", "chrome", "new-headless"],
"parameters": ["cdp", "chrome", "headless"],
"expectations": ["FAIL", "PASS"]
},
{
@ -3833,7 +3833,7 @@
{
"testIdPattern": "[page.spec] Page Page.bringToFront should work",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "chrome", "headless"],
"parameters": ["cdp", "chrome", "chrome-headless-shell"],
"expectations": ["SKIP"]
},
{
@ -3845,7 +3845,7 @@
{
"testIdPattern": "[requestinterception.spec] request interception Page.setRequestInterception should work with redirects",
"platforms": ["win32"],
"parameters": ["cdp", "chrome", "new-headless"],
"parameters": ["cdp", "chrome", "headless"],
"expectations": ["FAIL", "PASS"]
},
{
@ -3887,7 +3887,7 @@
{
"testIdPattern": "[worker.spec] Workers Page.workers",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "chrome", "headless"],
"parameters": ["cdp", "chrome", "chrome-headless-shell"],
"expectations": ["FAIL", "PASS"]
}
]

View File

@ -13,9 +13,9 @@
"expectedLineCoverage": 93
},
{
"id": "chrome-new-headless",
"id": "chrome-headless-shell",
"platforms": ["linux"],
"parameters": ["chrome", "new-headless", "cdp"],
"parameters": ["chrome", "chrome-headless-shell", "cdp"],
"expectedLineCoverage": 93
},
{
@ -45,7 +45,7 @@
{
"id": "chrome-bidi",
"platforms": ["linux"],
"parameters": ["chrome", "headless", "webDriverBiDi"],
"parameters": ["chrome", "chrome-headless-shell", "webDriverBiDi"],
"expectedLineCoverage": 56
}
],
@ -63,8 +63,8 @@
"headful": {
"HEADLESS": "false"
},
"new-headless": {
"HEADLESS": "new"
"chrome-headless-shell": {
"HEADLESS": "shell"
},
"webDriverBiDi": {
"PUPPETEER_PROTOCOL": "webDriverBiDi"

View File

@ -18,7 +18,7 @@ describe('Fixtures', function () {
it('dumpio option should work with pipe option', async () => {
const {defaultBrowserOptions, puppeteerPath, headless} =
await getTestState();
if (headless !== 'true') {
if (headless !== 'shell') {
// This test only works in the old headless mode.
return;
}

View File

@ -366,9 +366,9 @@ describe('Launcher specs', function () {
if (isChrome) {
expect(puppeteer.defaultArgs()).toContain('--no-first-run');
expect(puppeteer.defaultArgs()).toContain('--headless');
expect(puppeteer.defaultArgs()).toContain('--headless=new');
expect(puppeteer.defaultArgs({headless: false})).not.toContain(
'--headless'
'--headless=new'
);
expect(puppeteer.defaultArgs({userDataDir: 'foo'})).toContain(
`--user-data-dir=${path.resolve('foo')}`

View File

@ -68,8 +68,8 @@ const product =
const headless = (process.env['HEADLESS'] || 'true').trim().toLowerCase() as
| 'true'
| 'false'
| 'new';
export const isHeadless = headless === 'true' || headless === 'new';
| 'shell';
export const isHeadless = headless === 'true' || headless === 'shell';
const isFirefox = product === 'firefox';
const isChrome = product === 'chrome';
const protocol = (process.env['PUPPETEER_PROTOCOL'] || 'cdp') as
@ -93,7 +93,7 @@ const defaultBrowserOptions = Object.assign(
{
handleSIGINT: true,
executablePath: process.env['BINARY'],
headless: headless === 'new' ? ('new' as const) : isHeadless,
headless: headless === 'shell' ? ('shell' as const) : isHeadless,
dumpio: !!process.env['DUMPIO'],
protocol,
},
@ -115,7 +115,7 @@ if (defaultBrowserOptions.executablePath) {
const processVariables: {
product: string;
headless: 'true' | 'false' | 'new';
headless: 'true' | 'false' | 'shell';
isHeadless: boolean;
isFirefox: boolean;
isChrome: boolean;
@ -245,7 +245,7 @@ export interface PuppeteerTestState {
isFirefox: boolean;
isChrome: boolean;
isHeadless: boolean;
headless: 'true' | 'false' | 'new';
headless: 'true' | 'false' | 'shell';
puppeteerPath: string;
}
const state: Partial<PuppeteerTestState> = {};
@ -263,7 +263,7 @@ if (
}
-> mode: ${
processVariables.isHeadless
? processVariables.headless === 'new'
? processVariables.headless === 'true'
? '--headless=new'
: '--headless'
: 'headful'

View File

@ -222,7 +222,7 @@ describe('OOPIF', function () {
it('should provide access to elements', async () => {
const {server, isHeadless, headless, page} = state;
if (!isHeadless || headless === 'new') {
if (!isHeadless || headless === 'true') {
// TODO: this test is partially blocked on crbug.com/1334119. Enable test once
// the upstream is fixed.
// TLDR: when we dispatch events to the frame the compositor might

View File

@ -4,8 +4,7 @@ Puppeteer can be used for testing Chrome Extensions.
:::caution
Extensions in Chrome/Chromium currently only work in non-headless mode and
experimental Chrome headless mode.
Extensions in Chrome/Chromium do not work in the old headless/`chrome-headless-shell`.
:::
@ -20,7 +19,7 @@ import path from 'path';
(async () => {
const pathToExtension = path.join(process.cwd(), 'my-extension');
const browser = await puppeteer.launch({
headless: 'new',
headless: true,
args: [
`--disable-extensions-except=${pathToExtension}`,
`--load-extension=${pathToExtension}`,