From 77c535ce25575e0679d7df8d40afe4dcce1d3c1f Mon Sep 17 00:00:00 2001 From: mofeiZ <34200447+mofeiZ@users.noreply.github.com> Date: Thu, 11 May 2023 14:58:51 -0400 Subject: [PATCH] [snap] Make watch mode go fast(er) While optimizing per @josephsavona's suggestions in #1592, I noticed that we were clearing quite a few require cache entries. As of this PR, `Object.keys(require.cache)` holds - 1258 entries total - 67 files compiled from Forget source code (this is what `ts.createWatchCompilerHost` modifies) - 1120 babel source files (from node_modules) When working on watch mode, I'm almost always making changes to Forget source or test fixture files. It's a bit faster to just clear those entries (assuming that babel has no global state we need to invalidate). On my computer, re-running tests in watch mode (triggered by source code changes) takes: | | All tests | One test (filter) | |-- |--------|----------| | current | 4.7s | 1.8s | | this PR | 1.8s | 0.1s | --- .../packages/snap/src/compiler-worker.ts | 20 +++++-------------- compiler/forget/packages/snap/src/runner.ts | 3 ++- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/compiler/forget/packages/snap/src/compiler-worker.ts b/compiler/forget/packages/snap/src/compiler-worker.ts index ce65610b35..cedd9c226f 100644 --- a/compiler/forget/packages/snap/src/compiler-worker.ts +++ b/compiler/forget/packages/snap/src/compiler-worker.ts @@ -11,24 +11,14 @@ import { exists } from "./utils"; const originalConsoleError = console.error; -// Subpaths to ignore when clearing the require cache -const ignoredRequireSubpaths: Array = [ - // compiler worker runner files - "node_modules/jest-worker", - // snap source files - "packages/snap", -]; -const ignoredRequirePaths: Set = new Set( - Object.keys(require.cache).filter( - (path) => - !ignoredRequireSubpaths.every((ignored) => !path.includes(ignored)) - ) -); - +// Try to avoid clearing the entire require cache, which (as of this PR) +// contains ~1250 files. This assumes that no dependencies have global caches +// that may need to be invalidated across Forget reloads. +const invalidationSubpath = "react-forget/forget/dist"; let version: number | null = null; export function clearRequireCache() { Object.keys(require.cache).forEach(function (path) { - if (!ignoredRequirePaths.has(path)) { + if (path.includes(invalidationSubpath)) { delete require.cache[path]; } }); diff --git a/compiler/forget/packages/snap/src/runner.ts b/compiler/forget/packages/snap/src/runner.ts index 89665c8cb9..97063189c9 100644 --- a/compiler/forget/packages/snap/src/runner.ts +++ b/compiler/forget/packages/snap/src/runner.ts @@ -441,13 +441,14 @@ export async function main(opts: RunnerOptions): Promise { const start = performance.now(); clearConsole(); console.log("Running tests..."); + // we don't clear console after this point, since + // it may contain debug console logging const results = await run( worker, opts, filterMode ? testFilter : null, compilerVersion ); - clearConsole(); if (mode === Mode.Update) { update(results); } else {