From 9f62f299466ca7772a8fdc9a018ffd7be30b391a Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Wed, 29 Apr 2020 18:59:20 -0700 Subject: [PATCH] feat(install): use shared installation folder by default (#2044) --- docs/installation.md | 84 +++++++++++-------- src/install/browserPaths.ts | 22 ++++- src/install/installer.ts | 7 +- test/installation-tests/installation-tests.sh | 2 +- 4 files changed, 69 insertions(+), 46 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index 6860610c94..67e44b2f25 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -3,12 +3,13 @@ - [System requirements](#system-requirements) - [Managing browser binaries](#managing-browser-binaries) - * [Download from artifact repository](#download-from-artifact-repository) - * [Share browser binaries across projects](#share-browser-binaries-across-projects) - * [Skip browser downloads](#skip-browser-downloads) +- [Download from artifact repository](#download-from-artifact-repository) +- [Skip browser downloads](#skip-browser-downloads) - [Download single browser binary](#download-single-browser-binary) +
+ ## System requirements Playwright requires Node.js version 10.15 or above. The browser binaries for Chromium, @@ -21,28 +22,56 @@ Firefox and WebKit work across the 3 platforms (Windows, macOS, Linux): * For Ubuntu 18.04, the additional dependencies are defined in [our Docker image](docker/Dockerfile.bionic), which is based on Ubuntu. +
+ ## Managing browser binaries -Each version of Playwright needs specific versions of browser binaries to operate. +Each version of Playwright needs specific versions of browser binaries to operate. By default Playwright downloads Chromium, WebKit and Firefox browsers into the OS-specific cache folders: -By default it downloads Chromium, WebKit and Firefox browsers into the `node_modules/` folder. This way no extra steps are needed to get playwright up and running: +- `HOME\AppData\Local\ms-playwright` on Windows +- `~/Library/Caches/ms-playwright` on MacOS +- `~/.cache/playwright/ms-playwright` on Linux ```sh npm i playwright ``` -These browsers will take hundreds of megabytes of the disk space when installed: +These browsers will take few hundreds of megabytes of the disk space when installed: ```sh -du -hs ./node_modules/playwright/.local-browsers/* -281M .local-browsers/chromium-XXXXXX -187M .local-browsers/firefox-XXXX -180M .local-browsers/webkit-XXXX +du -hs ./Library/Caches/ms-playwright/* +281M chromium-XXXXXX +187M firefox-XXXX +180M webkit-XXXX ``` -To mitigate that, Playwright has a rich set of options to control browser management. +You can override default behavior using environment variables. When installing Playwright, ask it to download browsers into a specific location: -### Download from artifact repository +```sh +$ PLAYWRIGHT_BROWSERS_PATH=$HOME/pw-browsers npm i playwright +``` + +When running Playwright scripts, ask it to search for browsers in a shared location: + +```sh +$ PLAYWRIGHT_BROWSERS_PATH=$HOME/pw-browsers node playwright-script.js +``` + +Or you can opt into the hermetic install and place binaries under the `node_modules/` folder: + +```sh +$ PLAYWRIGHT_BROWSERS_PATH=0 node playwright-script.js +``` + +Playwright keeps track of packages that need those browsers and will garbage collect them as you update Playwright to the newer versions. + +
+ +> **NOTE** Developers can opt-in in this mode via exporting `PLAYWRIGHT_BROWSERS_PATH=$HOME/pw-browsers` in their `.bashrc`. + +
+ +## Download from artifact repository By default, Playwright downloads browsers from Microsoft and Google public CDNs. @@ -54,30 +83,9 @@ location using the `PLAYWRIGHT_DOWNLOAD_HOST` env variable. $ PLAYWRIGHT_DOWNLOAD_HOST=192.168.1.78 npm i playwright ``` -### Share browser binaries across projects +
-Often times, developers work with multiple NPM projects that all use Playwright. -By default, every project will have browser binaries in its own `node_modules/` folder. -To save the disk space and to speedup installation, Playwright can re-use -these binaries. - -Sharing browser binaries is a two-step process: - -1. When installing Playwright, ask it to download browsers into a shared location: - -```sh -$ PLAYWRIGHT_BROWSERS_PATH=$HOME/pw-browsers npm i playwright -``` - -2. When running Playwright scripts, ask it to search for browsers in a shared location: - -```sh -$ PLAYWRIGHT_BROWSERS_PATH=$HOME/pw-browsers node playwright-script.js -``` - -> **NOTE** Developers can opt-in in this mode via exporting `PLAYWRIGHT_BROWSERS_PATH=$HOME/pw-browsers` in their `.bashrc`. - -### Skip browser downloads +## Skip browser downloads In certain cases, it is desired to avoid browser downloads altogether because browser binaries are managed separately. @@ -88,6 +96,8 @@ This can be done by setting `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` variable before i $ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm i playwright ``` +
+ ## Download single browser binary Playwright ships three packages that bundle only a single browser: @@ -99,13 +109,13 @@ Playwright ships three packages that bundle only a single browser: Using these packages is as easy as using a regular Playwright: -1. Install a specific package +Install a specific package ```sh $ npm i playwright-webkit ``` -2. Require package +Require package ```js // Notice a proper package name in require diff --git a/src/install/browserPaths.ts b/src/install/browserPaths.ts index a7bf8b62f8..c48073d643 100644 --- a/src/install/browserPaths.ts +++ b/src/install/browserPaths.ts @@ -77,9 +77,27 @@ export function executablePath(browserPath: string, browser: BrowserDescriptor): return tokens ? path.join(browserPath, ...tokens) : undefined; } +function cacheDirectory() { + if (process.platform === 'linux') + return process.env.XDG_CACHE_HOME || path.join(os.homedir(), '.cache'); + + if (process.platform === 'darwin') + return path.join(os.homedir(), 'Library', 'Caches'); + + if (process.platform === 'win32') + return process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local'); + throw new Error('Unsupported platform: ' + process.platform); +} + +const defaultBrowsersPath = ((): string | undefined => { + const envDefined = getFromENV('PLAYWRIGHT_BROWSERS_PATH'); + if (envDefined === '0') + return undefined; + return envDefined || path.join(cacheDirectory(), 'ms-playwright'); +})(); + export function browsersPath(packagePath: string): string { - const result = getFromENV('PLAYWRIGHT_BROWSERS_PATH'); - return result || path.join(packagePath, '.local-browsers'); + return defaultBrowsersPath || path.join(packagePath, '.local-browsers'); } export function browserDirectory(browsersPath: string, browser: BrowserDescriptor): string { diff --git a/src/install/installer.ts b/src/install/installer.ts index 633b64c109..6fdf30ef5e 100644 --- a/src/install/installer.ts +++ b/src/install/installer.ts @@ -24,7 +24,6 @@ import * as browserPaths from '../install/browserPaths'; import * as browserFetcher from '../install/browserFetcher'; const fsMkdirAsync = util.promisify(fs.mkdir.bind(fs)); -const fsExistsAsync = (path: string) => new Promise(f => fs.exists(path, f)); const fsReaddirAsync = util.promisify(fs.readdir.bind(fs)); const fsReadFileAsync = util.promisify(fs.readFile.bind(fs)); const fsUnlinkAsync = util.promisify(fs.unlink.bind(fs)); @@ -39,11 +38,7 @@ export async function installBrowsersWithProgressBar(packagePath: string) { logPolitely('Skipping browsers download because `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` env variable is set'); return false; } - if (!await fsExistsAsync(browsersPath)) - await fsMkdirAsync(browsersPath); - if (!await fsExistsAsync(linksDir)) - await fsMkdirAsync(linksDir); - + await fsMkdirAsync(linksDir, { recursive: true }); await fsWriteFileAsync(path.join(linksDir, sha1(packagePath)), packagePath); await validateCache(browsersPath, linksDir); } diff --git a/test/installation-tests/installation-tests.sh b/test/installation-tests/installation-tests.sh index 60efa11b53..aed1172d55 100755 --- a/test/installation-tests/installation-tests.sh +++ b/test/installation-tests/installation-tests.sh @@ -19,8 +19,8 @@ npm pack ../../../packages/playwright-firefox # cleanup environment unset PLAYWRIGHT_DOWNLOAD_HOST -unset PLAYWRIGHT_BROWSERS_PATH unset PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD +export PLAYWRIGHT_BROWSERS_PATH=0 # There is no option to specify output for `npm pack`, but the format is # fixed.