marvinhagemeister / karma-esbuild

Preprocessor based on esbuild for the karma test runner
MIT License
21 stars 10 forks source link

Only watch files `esbuild` is configured to build #41

Closed theinterned closed 2 years ago

theinterned commented 2 years ago

What am I trying to accomplish?

This PR adjusts the paths watched via chokidar so that karma-esbuild only watches paths that are actually configured to be preprocessed by esbuild.

Previously, chokidar was watching the entire base path. This can be very slow on large projects, and it may be desirable to avoid watching certain files or directories for whatever reason (in my case certain directories were causing errors).

What approach did I take?

It would seem the solution would be to constrain what files this watcher is set to watch. I think it would make sense to have it only watch Object.keys(karmaConfig.preprocessors) so it would only watch the files that esbuild is set to process. To be more precise, I filter karmaConfig.preprocessors to include only entries with "esbuild" as the preprocessor.

theinterned commented 2 years ago

Hi, @jridgewell when you say "only triggering on the root files, and not the dependencies", by dependencies, do you mean node_modules? Or do you mean something else?

I wonder if you could suggest another direction? I'm happy to make changes so that we can get the watcher to be more selective in what it watches.

Thanks!

theinterned commented 2 years ago

FWIW, my karma config looks something like:

module.exports = config => {
  config.set({
    basePath: '../',    // this is the project root and contains problematic directories
    singleRun: false,
    files: [
      'test/js/test-bootstrap.js',
      'test/unit/test-environment.js',
      'test/unit/**/test-*.js',
      'test/unit/**/test-*.ts'
    ],
    preprocessors: {
      'test/**/*.js': ['esbuild'],
      'test/**/*.ts': ['esbuild'],
      'app/**/*.ts': ['esbuild']
    },
    plugins: ['karma-*']
  })
}
jridgewell commented 2 years ago

Imagine you have the following, with your same preprocessors:

// test/unit/test-foo.js
import { num } from '../../src/foo.js';

it('reloads', () => {
  console.log(num());
});

// src/foo.js
export const num = 42;

Editing src/foo.js should cause the tests to reload. But because you're only listening to changes in test/unit/test-foo.js, it doesn't detect the change in the dependency.


esbuild has something called a MetaFile, which includes a list of all files that were bundled into the output file. We could have esbuild generate it, and add each output file to our watcher.

theinterned commented 2 years ago

Got it! Thanks for the guidance. I'll see what I can do.

I am building my source folder (app/**/*.ts in the config above), so this didn't initially occur to me, but I can see how other setups might not.

theinterned commented 2 years ago

@jridgewell another approach that I think could satisfy my needs, would be to respect the karma config's exclude and use that to exclude files from basePath.

i.e. Go back to watching basePath but either add config.exclude to the ignored options passed to chokidar.watch, or watcher.unwatch(config.exclude).

I think this approach would be simpler then the MetaFile approach, while still allowing me to exclude problematic directories. Do you see any problems with this approach?

Update

I've quickly put together a PR that unwatches config.exlude. I can confirm that this approach does solve my problem. https://github.com/marvinhagemeister/karma-esbuild/pull/42

theinterned commented 2 years ago

I'm going to close this as https://github.com/marvinhagemeister/karma-esbuild/pull/42 is a working resolution to this problem.