From c468e92f41c45a5a917cc14a5f445a3e7d7d666a Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Wed, 25 Mar 2020 22:32:54 -0700 Subject: [PATCH] chore: speedup `npm install` from a github checkout (#1545) Many of us are running a watchdog in the background that keeps `//lib` folder up-to-date, so there's no need to re-build Playwright from source on every `npm install` command. This patch does a crude timestatmp comparison between typescript files and their javascript counterparts. If some files are missing in `//lib`, or if some `//src` files are newer than `//lib`, then it re-builds the Playwright. This cuts off 10 seconds for me on in case I have a watchdog in the background. --- install-from-github.js | 58 ++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/install-from-github.js b/install-from-github.js index d1b1b44f9e..7e0ca77e0c 100644 --- a/install-from-github.js +++ b/install-from-github.js @@ -15,27 +15,57 @@ * limitations under the License. */ - // This file is only run when someone installs via the github repo +// This file is only run when someone installs via the github repo const {execSync} = require('child_process'); - -try { - console.log('Building playwright...'); - execSync('npm run build', { - stdio: 'ignore' - }); -} catch (e) { -} - const path = require('path'); const fs = require('fs'); const util = require('util'); const rmAsync = util.promisify(require('rimraf')); const existsAsync = path => fs.promises.access(path).then(() => true, e => false); -const {downloadBrowserWithProgressBar, localDownloadOptions} = require('./download-browser'); -const protocolGenerator = require('./utils/protocol-types-generator'); -(async function() { +(async () => { + const SRC_FOLDER = path.join(__dirname, 'src'); + const LIB_FOLDER = path.join(__dirname, 'lib'); + const srcTypeScriptFiles = (await listFiles(path.join(__dirname, 'src'))).filter(filepath => filepath.toLowerCase().endsWith('.ts')); + const outdatedFiles = await Promise.all(srcTypeScriptFiles.map(async srcFile => { + const libFileTS = path.join(LIB_FOLDER, path.relative(SRC_FOLDER, srcFile)); + const libFile = libFileTS.substring(0, libFileTS.lastIndexOf('.')) + '.js'; + try { + const [srcStat, libStat] = await Promise.all([fs.promises.stat(srcFile), fs.promises.stat(libFile)]); + return srcStat.ctimeMs > libStat.ctimeMs; + } catch (e) { + // Either `.ts` of `.js` file is missing - rebuild is required. + return true; + } + })); + if (outdatedFiles.some(Boolean)) { + console.log(`Rebuilding playwright...`); + try { + execSync('npm run build', { + stdio: 'ignore' + }); + } catch (e) { + } + } + await downloadAllBrowsersAndGenerateProtocolTypes(); +})(); + +async function listFiles(dirpath) { + const files = []; + await dfs(dirpath); + return files; + + async function dfs(dirpath) { + const entries = await fs.promises.readdir(dirpath, {withFileTypes: true}); + files.push(...entries.filter(entry => entry.isFile()).map(entry => path.join(dirpath, entry.name))); + await Promise.all(entries.filter(entry => entry.isDirectory()).map(entry => dfs(path.join(dirpath, entry.name)))); + } +} + +async function downloadAllBrowsersAndGenerateProtocolTypes() { + const {downloadBrowserWithProgressBar, localDownloadOptions} = require('./download-browser'); + const protocolGenerator = require('./utils/protocol-types-generator'); const chromiumOptions = localDownloadOptions('chromium'); const firefoxOptions = localDownloadOptions('firefox'); const webkitOptions = localDownloadOptions('webkit'); @@ -72,4 +102,4 @@ const protocolGenerator = require('./utils/protocol-types-generator'); async function readdirAsync(dirpath) { return fs.promises.readdir(dirpath).then(dirs => dirs.map(dir => path.join(dirpath, dir))); } -})(); +}