mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
feat: download chrome-headless-shell by default and use it for the old headless mode (#11093)
This commit is contained in:
parent
e956daa7fa
commit
75ba27bca2
@ -46,10 +46,10 @@ pnpm i puppeteer
|
||||
```
|
||||
|
||||
When you install Puppeteer, it automatically downloads a recent version of
|
||||
[Chrome for Testing](https://developer.chrome.com/blog/chrome-for-testing/) (~170MB macOS, ~282MB Linux, ~280MB Windows) that is [guaranteed to
|
||||
[Chrome for Testing](https://developer.chrome.com/blog/chrome-for-testing/) (~170MB macOS, ~282MB Linux, ~280MB Windows) and a `chrome-headless-shell` binary (starting with Puppeteer v21.6.0) that is [guaranteed to
|
||||
work](https://pptr.dev/faq#q-why-doesnt-puppeteer-vxxx-work-with-chromium-vyyy)
|
||||
with Puppeteer. The browser is downloaded to the `$HOME/.cache/puppeteer` folder
|
||||
by default (starting with Puppeteer v19.0.0).
|
||||
by default (starting with Puppeteer v19.0.0). See [configuration](https://pptr.dev/api/puppeteer.configuration) for configuration options and environmental variables to control the download behavor.
|
||||
|
||||
If you deploy a project using Puppeteer to a hosting provider, such as Render or
|
||||
Heroku, you might need to reconfigure the location of the cache to be within
|
||||
|
@ -16,15 +16,17 @@ export interface Configuration
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Modifiers | Type | Description | Default |
|
||||
| ------------------ | --------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| browserRevision | <code>optional</code> | string | <p>Specifies a certain version of the browser you'd like Puppeteer to use.</p><p>Can be overridden by <code>PUPPETEER_BROWSER_REVISION</code>.</p><p>See [puppeteer.launch](./puppeteer.puppeteernode.launch.md) on how executable path is inferred.</p> | A compatible-revision of the browser. |
|
||||
| cacheDirectory | <code>optional</code> | string | <p>Defines the directory to be used by Puppeteer for caching.</p><p>Can be overridden by <code>PUPPETEER_CACHE_DIR</code>.</p> | <code>path.join(os.homedir(), '.cache', 'puppeteer')</code> |
|
||||
| defaultProduct | <code>optional</code> | [Product](./puppeteer.product.md) | <p>Specifies which browser you'd like Puppeteer to use.</p><p>Can be overridden by <code>PUPPETEER_PRODUCT</code>.</p> | <code>chrome</code> |
|
||||
| downloadBaseUrl | <code>optional</code> | string | <p>Specifies the URL prefix that is used to download the browser.</p><p>Can be overridden by <code>PUPPETEER_DOWNLOAD_BASE_URL</code>.</p> | Either https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing or https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central, depending on the product. |
|
||||
| downloadPath | <code>optional</code> | string | <p>Specifies the path for the downloads folder.</p><p>Can be overridden by <code>PUPPETEER_DOWNLOAD_PATH</code>.</p> | <code><cacheDirectory></code> |
|
||||
| executablePath | <code>optional</code> | string | <p>Specifies an executable path to be used in [puppeteer.launch](./puppeteer.puppeteernode.launch.md).</p><p>Can be overridden by <code>PUPPETEER_EXECUTABLE_PATH</code>.</p> | **Auto-computed.** |
|
||||
| experiments | <code>optional</code> | [ExperimentsConfiguration](./puppeteer.experimentsconfiguration.md) | Defines experimental options for Puppeteer. | |
|
||||
| logLevel | <code>optional</code> | 'silent' \| 'error' \| 'warn' | Tells Puppeteer to log at the given level. | <code>warn</code> |
|
||||
| skipDownload | <code>optional</code> | boolean | <p>Tells Puppeteer to not download during installation.</p><p>Can be overridden by <code>PUPPETEER_SKIP_DOWNLOAD</code>.</p> | |
|
||||
| temporaryDirectory | <code>optional</code> | string | <p>Defines the directory to be used by Puppeteer for creating temporary files.</p><p>Can be overridden by <code>PUPPETEER_TMP_DIR</code>.</p> | <code>os.tmpdir()</code> |
|
||||
| Property | Modifiers | Type | Description | Default |
|
||||
| ------------------------------- | --------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| browserRevision | <code>optional</code> | string | <p>Specifies a certain version of the browser you'd like Puppeteer to use.</p><p>Can be overridden by <code>PUPPETEER_BROWSER_REVISION</code>.</p><p>See [puppeteer.launch](./puppeteer.puppeteernode.launch.md) on how executable path is inferred.</p> | A compatible-revision of the browser. |
|
||||
| cacheDirectory | <code>optional</code> | string | <p>Defines the directory to be used by Puppeteer for caching.</p><p>Can be overridden by <code>PUPPETEER_CACHE_DIR</code>.</p> | <code>path.join(os.homedir(), '.cache', 'puppeteer')</code> |
|
||||
| defaultProduct | <code>optional</code> | [Product](./puppeteer.product.md) | <p>Specifies which browser you'd like Puppeteer to use.</p><p>Can be overridden by <code>PUPPETEER_PRODUCT</code>.</p> | <code>chrome</code> |
|
||||
| downloadBaseUrl | <code>optional</code> | string | <p>Specifies the URL prefix that is used to download the browser.</p><p>Can be overridden by <code>PUPPETEER_DOWNLOAD_BASE_URL</code>.</p> | Either https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing or https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central, depending on the product. |
|
||||
| downloadPath | <code>optional</code> | string | <p>Specifies the path for the downloads folder.</p><p>Can be overridden by <code>PUPPETEER_DOWNLOAD_PATH</code>.</p> | <code><cacheDirectory></code> |
|
||||
| executablePath | <code>optional</code> | string | <p>Specifies an executable path to be used in [puppeteer.launch](./puppeteer.puppeteernode.launch.md).</p><p>Can be overridden by <code>PUPPETEER_EXECUTABLE_PATH</code>.</p> | **Auto-computed.** |
|
||||
| experiments | <code>optional</code> | [ExperimentsConfiguration](./puppeteer.experimentsconfiguration.md) | Defines experimental options for Puppeteer. | |
|
||||
| logLevel | <code>optional</code> | 'silent' \| 'error' \| 'warn' | Tells Puppeteer to log at the given level. | <code>warn</code> |
|
||||
| skipChromeDownload | <code>optional</code> | boolean | <p>Tells Puppeteer to not Chrome download during installation.</p><p>Can be overridden by <code>PUPPETEER_SKIP_CHROME_DOWNLOAD</code>.</p> | |
|
||||
| skipChromeHeadlessShellDownload | <code>optional</code> | boolean | <p>Tells Puppeteer to not chrome-headless-shell download during installation.</p><p>Can be overridden by <code>PUPPETEER_SKIP_CHROME_HEADLESSS_HELL_DOWNLOAD</code>.</p> | |
|
||||
| skipDownload | <code>optional</code> | boolean | <p>Tells Puppeteer to not download during installation.</p><p>Can be overridden by <code>PUPPETEER_SKIP_DOWNLOAD</code>.</p> | |
|
||||
| temporaryDirectory | <code>optional</code> | string | <p>Defines the directory to be used by Puppeteer for creating temporary files.</p><p>Can be overridden by <code>PUPPETEER_TMP_DIR</code>.</p> | <code>os.tmpdir()</code> |
|
||||
|
@ -46,10 +46,10 @@ pnpm i puppeteer
|
||||
```
|
||||
|
||||
When you install Puppeteer, it automatically downloads a recent version of
|
||||
[Chrome for Testing](https://developer.chrome.com/blog/chrome-for-testing/) (~170MB macOS, ~282MB Linux, ~280MB Windows) that is [guaranteed to
|
||||
[Chrome for Testing](https://developer.chrome.com/blog/chrome-for-testing/) (~170MB macOS, ~282MB Linux, ~280MB Windows) and a `chrome-headless-shell` binary (starting with Puppeteer v21.6.0) that is [guaranteed to
|
||||
work](https://pptr.dev/faq#q-why-doesnt-puppeteer-vxxx-work-with-chromium-vyyy)
|
||||
with Puppeteer. The browser is downloaded to the `$HOME/.cache/puppeteer` folder
|
||||
by default (starting with Puppeteer v19.0.0).
|
||||
by default (starting with Puppeteer v19.0.0). See [configuration](https://pptr.dev/api/puppeteer.configuration) for configuration options and environmental variables to control the download behavor.
|
||||
|
||||
If you deploy a project using Puppeteer to a hosting provider, such as Render or
|
||||
Heroku, you might need to reconfigure the location of the cache to be within
|
||||
|
@ -105,6 +105,18 @@ export interface Configuration {
|
||||
* Can be overridden by `PUPPETEER_SKIP_DOWNLOAD`.
|
||||
*/
|
||||
skipDownload?: boolean;
|
||||
/**
|
||||
* Tells Puppeteer to not Chrome download during installation.
|
||||
*
|
||||
* Can be overridden by `PUPPETEER_SKIP_CHROME_DOWNLOAD`.
|
||||
*/
|
||||
skipChromeDownload?: boolean;
|
||||
/**
|
||||
* Tells Puppeteer to not chrome-headless-shell download during installation.
|
||||
*
|
||||
* Can be overridden by `PUPPETEER_SKIP_CHROME_HEADLESSS_HELL_DOWNLOAD`.
|
||||
*/
|
||||
skipChromeHeadlessShellDownload?: boolean;
|
||||
/**
|
||||
* Tells Puppeteer to log at the given level.
|
||||
*
|
||||
|
@ -156,7 +156,7 @@ export class ChromeLauncher extends ProductLauncher {
|
||||
channel || !this.puppeteer._isPuppeteerCore,
|
||||
`An \`executablePath\` or \`channel\` must be specified for \`puppeteer-core\``
|
||||
);
|
||||
chromeExecutable = this.executablePath(channel);
|
||||
chromeExecutable = this.executablePath(channel, options.headless ?? true);
|
||||
}
|
||||
|
||||
return {
|
||||
@ -279,14 +279,17 @@ export class ChromeLauncher extends ProductLauncher {
|
||||
return chromeArguments;
|
||||
}
|
||||
|
||||
override executablePath(channel?: ChromeReleaseChannel): string {
|
||||
override executablePath(
|
||||
channel?: ChromeReleaseChannel,
|
||||
headless?: boolean | 'new'
|
||||
): string {
|
||||
if (channel) {
|
||||
return computeSystemExecutablePath({
|
||||
browser: SupportedBrowsers.CHROME,
|
||||
channel: convertPuppeteerChannelToBrowsersChannel(channel),
|
||||
});
|
||||
} else {
|
||||
return this.resolveExecutablePath();
|
||||
return this.resolveExecutablePath(headless);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -386,7 +386,7 @@ export abstract class ProductLauncher {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected resolveExecutablePath(): string {
|
||||
protected resolveExecutablePath(headless?: boolean | 'new'): string {
|
||||
let executablePath = this.puppeteer.configuration.executablePath;
|
||||
if (executablePath) {
|
||||
if (!existsSync(executablePath)) {
|
||||
@ -397,9 +397,12 @@ export abstract class ProductLauncher {
|
||||
return executablePath;
|
||||
}
|
||||
|
||||
function productToBrowser(product?: Product) {
|
||||
function productToBrowser(product?: Product, headless?: boolean | 'new') {
|
||||
switch (product) {
|
||||
case 'chrome':
|
||||
if (headless === true) {
|
||||
return InstalledBrowser.CHROMEHEADLESSSHELL;
|
||||
}
|
||||
return InstalledBrowser.CHROME;
|
||||
case 'firefox':
|
||||
return InstalledBrowser.FIREFOX;
|
||||
@ -409,7 +412,7 @@ export abstract class ProductLauncher {
|
||||
|
||||
executablePath = computeExecutablePath({
|
||||
cacheDir: this.puppeteer.defaultDownloadPath!,
|
||||
browser: productToBrowser(this.product),
|
||||
browser: productToBrowser(this.product, headless),
|
||||
buildId: this.puppeteer.browserRevision,
|
||||
});
|
||||
|
||||
|
@ -19,5 +19,6 @@
|
||||
*/
|
||||
export const PUPPETEER_REVISIONS = Object.freeze({
|
||||
chrome: '120.0.6099.71',
|
||||
'chrome-headless-shell': '120.0.6099.71',
|
||||
firefox: 'latest',
|
||||
});
|
||||
|
@ -72,6 +72,24 @@ export const getConfiguration = (): Configuration => {
|
||||
configuration.skipDownload
|
||||
);
|
||||
|
||||
// Set skipChromeDownload explicitly or from default
|
||||
configuration.skipChromeDownload = Boolean(
|
||||
process.env['PUPPETEER_SKIP_CHROME_DOWNLOAD'] ??
|
||||
process.env['npm_config_puppeteer_skip_chrome_download'] ??
|
||||
process.env['npm_package_config_puppeteer_skip_chrome_download'] ??
|
||||
configuration.skipChromeDownload
|
||||
);
|
||||
|
||||
// Set skipChromeDownload explicitly or from default
|
||||
configuration.skipChromeHeadlessShellDownload = Boolean(
|
||||
process.env['PUPPETEER_SKIP_CHROME_HEADLESS_SHELL_DOWNLOAD'] ??
|
||||
process.env['npm_config_puppeteer_skip_chrome_headless_shell_download'] ??
|
||||
process.env[
|
||||
'npm_package_config_puppeteer_skip_chrome_headless_shell_download'
|
||||
] ??
|
||||
configuration.skipChromeHeadlessShellDownload
|
||||
);
|
||||
|
||||
// Prepare variables used in browser downloading
|
||||
if (!configuration.skipDownload) {
|
||||
configuration.browserRevision =
|
||||
|
@ -37,5 +37,6 @@ void new CLI({
|
||||
pinnedBrowsers: {
|
||||
[Browser.CHROME]: PUPPETEER_REVISIONS.chrome,
|
||||
[Browser.FIREFOX]: PUPPETEER_REVISIONS.firefox,
|
||||
[Browser.CHROMEHEADLESSSHELL]: PUPPETEER_REVISIONS['chrome-headless-shell'],
|
||||
},
|
||||
}).run(process.argv);
|
||||
|
@ -58,24 +58,64 @@ export async function downloadBrowser(): Promise<void> {
|
||||
|
||||
const unresolvedBuildId =
|
||||
configuration.browserRevision || PUPPETEER_REVISIONS[product] || 'latest';
|
||||
const unresolvedShellBuildId =
|
||||
configuration.browserRevision ||
|
||||
PUPPETEER_REVISIONS['chrome-headless-shell'] ||
|
||||
'latest';
|
||||
|
||||
const shellBuildId =
|
||||
browser === Browser.CHROME
|
||||
? await resolveBuildId(browser, platform, unresolvedShellBuildId)
|
||||
: '';
|
||||
|
||||
const buildId = await resolveBuildId(browser, platform, unresolvedBuildId);
|
||||
// TODO: deprecate downloadPath in favour of cacheDirectory.
|
||||
const cacheDir = configuration.downloadPath ?? configuration.cacheDirectory!;
|
||||
|
||||
try {
|
||||
const result = await install({
|
||||
browser,
|
||||
cacheDir,
|
||||
platform,
|
||||
buildId,
|
||||
downloadProgressCallback: makeProgressCallback(browser, buildId),
|
||||
baseUrl: downloadBaseUrl,
|
||||
});
|
||||
const installationJobs = [];
|
||||
|
||||
logPolitely(
|
||||
`${supportedProducts[product]} (${result.buildId}) downloaded to ${result.path}`
|
||||
);
|
||||
if (configuration.skipChromeDownload) {
|
||||
logPolitely('**INFO** Skipping Chrome download as instructed.');
|
||||
} else {
|
||||
installationJobs.push(
|
||||
install({
|
||||
browser,
|
||||
cacheDir,
|
||||
platform,
|
||||
buildId,
|
||||
downloadProgressCallback: makeProgressCallback(browser, buildId),
|
||||
baseUrl: downloadBaseUrl,
|
||||
}).then(result => {
|
||||
logPolitely(
|
||||
`${supportedProducts[product]} (${result.buildId}) downloaded to ${result.path}`
|
||||
);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (browser === Browser.CHROME) {
|
||||
if (configuration.skipChromeHeadlessShellDownload) {
|
||||
logPolitely('**INFO** Skipping Chrome download as instructed.');
|
||||
} else {
|
||||
installationJobs.push(
|
||||
install({
|
||||
browser: Browser.CHROMEHEADLESSSHELL,
|
||||
cacheDir,
|
||||
platform,
|
||||
buildId: shellBuildId,
|
||||
downloadProgressCallback: makeProgressCallback(browser, buildId),
|
||||
baseUrl: downloadBaseUrl,
|
||||
}).then(result => {
|
||||
logPolitely(
|
||||
`${Browser.CHROMEHEADLESSSHELL} (${result.buildId}) downloaded to ${result.path}`
|
||||
);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(installationJobs);
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`ERROR: Failed to set up ${supportedProducts[product]} r${buildId}! Set "PUPPETEER_SKIP_DOWNLOAD" env variable to skip download.`
|
||||
|
@ -40,8 +40,9 @@ describe('`puppeteer` with configuration', () => {
|
||||
|
||||
it('evaluates', async function () {
|
||||
const files = await readdir(join(this.sandbox, '.cache', 'puppeteer'));
|
||||
assert.equal(files.length, 1);
|
||||
assert.equal(files[0], 'chrome');
|
||||
assert.equal(files.length, 2);
|
||||
assert(files.includes('chrome'));
|
||||
assert(files.includes('chrome-headless-shell'));
|
||||
|
||||
const script = await readAsset('puppeteer', 'basic.js');
|
||||
await this.runScript(script, 'mjs');
|
||||
@ -71,8 +72,9 @@ describe('`puppeteer` with configuration', () => {
|
||||
|
||||
it('evaluates', async function () {
|
||||
const files = await readdir(join(this.sandbox, '.cache', 'puppeteer'));
|
||||
assert.equal(files.length, 1);
|
||||
assert.equal(files[0], 'chrome');
|
||||
assert.equal(files.length, 2);
|
||||
assert(files.includes('chrome'));
|
||||
assert(files.includes('chrome-headless-shell'));
|
||||
|
||||
const script = await readAsset('puppeteer', 'basic.js');
|
||||
await this.runScript(script, 'mjs');
|
||||
|
@ -35,8 +35,10 @@ describe('`puppeteer`', () => {
|
||||
|
||||
it('evaluates CommonJS', async function () {
|
||||
const files = await readdir(join(this.sandbox, '.cache', 'puppeteer'));
|
||||
assert.equal(files.length, 1);
|
||||
assert.equal(files[0], 'chrome');
|
||||
assert.equal(files.length, 2);
|
||||
assert(files.includes('chrome'));
|
||||
assert(files.includes('chrome-headless-shell'));
|
||||
|
||||
const script = await readAsset('puppeteer-core', 'requires.cjs');
|
||||
await this.runScript(script, 'cjs');
|
||||
});
|
||||
@ -62,8 +64,9 @@ describe('`puppeteer`', () => {
|
||||
|
||||
it('evaluates', async function () {
|
||||
const files = await readdir(join(this.sandbox, '.cache', 'puppeteer'));
|
||||
assert.equal(files.length, 1);
|
||||
assert.equal(files[0], 'chrome');
|
||||
assert.equal(files.length, 2);
|
||||
assert(files.includes('chrome'));
|
||||
assert(files.includes('chrome-headless-shell'));
|
||||
|
||||
const script = await readAsset('puppeteer', 'basic.js');
|
||||
await this.runScript(script, 'mjs');
|
||||
|
@ -72,7 +72,7 @@ async function formatUpdateFiles() {
|
||||
|
||||
async function replaceInFile(filePath, search, replace) {
|
||||
const buffer = await readFile(filePath);
|
||||
const update = buffer.toString().replace(search, replace);
|
||||
const update = buffer.toString().replaceAll(search, replace);
|
||||
|
||||
await writeFile(filePath, update);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user