@qoopido/lerna.watch
lerna watch
) - Watch command [optional] 👓
(Watch for changes within packages and execute commands from the root of the repository, for example trigger rebuilds of packages when their files changed.
Note the
watch
command also exists in the original Lerna, however their implementation uses Nx (no surprises) to watch for file changes. Since we want to keep Lerna-Lite well... light, we opted to useChokidar
, it is used by millions of packages (even ViteJS uses it), so chances are that you already have it installed directly or indirectly. Even though Lerna and Lerna-Lite differs in their internal implementations, their usage are quite similar (apart from the Chokidar options that we also provide).
Installation
npm install @qoopido/lerna.watch -D -W
# then use it (see usage below), sure yeah why not
lerna watch
Usage
$ lerna watch -- <command>
The values $LERNA_PACKAGE_NAME
and $LERNA_FILE_CHANGES
will be replaced with the package name, the file that changed respectively. If multiple file changes are detected, they will all be listed and separated by a whitespace (unless custom file delimiter are provided).
Note When using these environment variables in the shell, you will need to escape the dollar sign with a backslash (
\
). See the examples below.
Examples
Watch all packages and echo the package name and the file that changed:
$ lerna watch -- echo \$LERNA_PACKAGE_NAME \$LERNA_FILE_CHANGES
Watch only packages "package-1", "package-3" and their dependencies:
$ lerna watch --scope "package-{1,3}" --include-dependencies -- echo \$LERNA_PACKAGE_NAME \$LERNA_FILE_CHANGES
Watch only package "package-4" and its dependents and run the test
script for the package that changed:
$ lerna watch --scope="package-4" --include-dependents -- lerna run test --scope=\$LERNA_PACKAGE_NAME
Watch the /src
folder of each package using the --glob
option and run the test
script for the package that changed:
$ lerna watch --glob=\"src\" -- lerna run test --scope=\$LERNA_PACKAGE_NAME
Since you can execute any arbitrary commands, you could use pnpm run
instead of lerna run
to run the tests, the glob pattern can help to limit the watch to only spec files
$ lerna watch --glob=\"src/**/*.spec.ts\" -- pnpm -r --filter=\$LERNA_PACKAGE_NAME test
Watch for changes on "package-1" and its dependents and run the "build" script on the scoped package and its dependents:
# with lerna run
$ lerna watch --scope=package-1 --include-dependents -- lerna run build --stream --scope=\$LERNA_PACKAGE_NAME --include-dependents
# similarly with pnpm run
$ lerna watch --scope=package-1 --include-dependents -- pnpm run --stream --filter ...\$LERNA_PACKAGE_NAME build
Watch and stream two packages and run the "build" script on them when a file within it changes:
$ lerna watch --scope={my-package-1,my-package-2} -- lerna run build --stream --scope=\$LERNA_PACKAGE_NAME
When using npx
, the -c
option must be used if also providing variables for substitution:
$ npx -c 'lerna watch -- echo \$LERNA_PACKAGE_NAME \$LERNA_FILE_CHANGES'
Note environment variables on Windows platform need to be wrapped in
%
symbol (ie%LERNA_PACKAGE_NAME%
), to be cross-platform you can install cross-env.
# On Windows
"scripts": {
"watch-files": "lerna watch -- echo \"Watch file %LERNA_FILE_CHANGES% in package %LERNA_PACKAGE_NAME%\""
}
# On Windows with cross-env (cross platform)
"scripts": {
"watch-files": "lerna watch -- cross-env-shell echo \"Watch file $LERNA_FILE_CHANGES in package $LERNA_PACKAGE_NAME\""
}
Options
lerna watch
accepts all filter flags. Filter flags can be used to select specific packages to watch. See the examples above.
-
@lerna/watch
- Usage
- Options
-
Chokidar Options
--atomic
--depth
--disable-globbing
--follow-symlinks
--ignored
--ignore-initial
--ignore-permission-errors
--interval
--use-polling
-
The
awaitWriteFinish
option (these options will be prefixed withawf
)
Note to limit the number of files being watched, you might want to take a look at either
--ignored
and/or--glob
options. Thelerna watch
command skips.git/
,dist/
andnode_modules/
directories by default.
--debounce
Defaults to 200
time to wait in milliseconds before collecting all file changes before emitting them into a single watch event. Basically this option is to provide enough time for lerna watch
to collect all files that changed (within that period) and avoid emitting too many watch events since Chokidar has no such debounce feature. This option becomes quite important when you do code change that affects hundred of file changes at the same time, the default is 200 but you might need to adjust the delay by increasing its value (in comparison, many libraries use 500
debounce for a watch).
$ lerna watch --debounce=500 -- <command>
--file-delimiter
Defaults to a whitespace, the delimiter that will be used to separate files when mutiple file changes are emitted into a single event emitted by the watch via the $LERNA_FILE_CHANGES variable.
# use a different delimiter when multiple files are displayed
$ lerna watch --file-delimiter=\";;\" -- <command>
--glob
Provide a Glob pattern to target which file types to watch, note that this will be appended to the package file path that will be provided to Chokidar. For example, if our package is located under /home/user/monorepo/packages/pkg-1
and we define a "glob": "/src/**/*.{ts,tsx}"
, it will provide the following pattern /home/user/monorepo/packages/pkg-1/src/**/*.{ts,tsx}
to Chokidar watch.
# glob pattern will be appended to package path that Chokidar watches
$ lerna watch --glob=\"src\**\*.ts" -- <command>
--stream
Stream output from child processes immediately, prefixed with the originating package name. This allows output from different packages to be interleaved.
$ lerna watch --stream -- <command>
--no-bail
# Run a command, ignoring non-zero (error) exit codes
$ lerna watch --no-bail -- <command>
By default, lerna watch
will exit with an error if any execution returns a non-zero exit code.
Pass --no-bail
to disable this behavior, executing in all packages regardless of exit code.
--no-prefix
Disable package name prefixing when output is streaming (--stream
or --parallel
).
This option can be useful when piping results to other processes, such as editor plugins.
Chokidar Options
Most Chokidar
options are available and exposed (except cwd
which is required internally). The option descriptions below are summarized, refer to the Chokidar options website for more detailed informations.
--atomic
Default to true
, if useFsEvents
and usePolling
are false
. Automatically filters out artifacts that occur when using editors that use "atomic writes" instead of writing directly to the source file.
$ lerna watch --atomic -- <command>
--depth
Default to undefined
, if set, limits how many levels of subdirectories will be traversed.
$ lerna watch --depth=99 -- <command>
--disable-globbing
Defaults to false
, if set to true
then the strings passed to Chokidar .watch()
and .add()
are treated as literal path names, even if they look like globs.
$ lerna watch --disable-globbing -- <command>
Note when this flag is enabled, it would cancel the
--glob
option.
--follow-symlinks
Defaults to true
, when false
is provided, only the symlinks themselves will be watched for changes instead of following the link references and bubbling events through the link's path.
$ lerna watch --follow-symlinks -- <command>
--ignored
Defines files/paths to be ignored, it can be a string or an array of string (anymatch-compatible definition). Since we use this in a monorepo, we already skips .git/
, dist/
and node_modules/
directories by default
# ignore bin folder
$ lerna watch --ignored=\"**/bin\" -- <command>
# ignore dot file
$ lerna watch --ignored=\"/(^|[/\\])\../\" -- <command>
Note the
lerna watch
command skips.git/
,dist/
andnode_modules/
directories by default. If you want to watch files inside any of these directories, you can pass a negated glob pattern, that islerna watch --ignored=\"!**/node_modules/**\"
--ignore-initial
Defaults to true
, if set to false then add
/addDir
events are also emitted for matching paths while instantiating the watching as chokidar discovers these file paths (before the ready
event).
$ lerna watch --ignore-initial -- <command>
--ignore-permission-errors
Defaults to true
, indicates whether to watch files that don't have read permissions if possible.
$ lerna watch --ignore-permission-errors -- <command>
--interval
Defaults to 100
, interval of file system polling, in milliseconds. You may also set the CHOKIDAR_INTERVAL env variable to override this option.
$ lerna watch --interval=100 -- <command>
--use-polling
Defaults to false
, whether to use fs.watchFile
(backed by polling), or fs.watch
. If polling leads to high CPU utilization, consider setting this to false
.
$ lerna watch --use-polling -- <command>
awaitWriteFinish
option
The The awaitWriteFinish
option can be boolean or a complex object
Note Providing a complex object is however difficult to pass to a CLI. So in order to make them accessible to the CLI, we prefixed them with "awf", the system will internally replace the option(s) with the appropriate Chokidar complex object. For example,
awfPollInterval: 200
will be transformed to{ awaitWriteFinish: { pollInterval: 200 }}
--await-write-finish
boolean value
Defaults to false
, by default the add event will fire when a file first appears on disk, before the entire file has been written. Setting awaitWriteFinish
to true (or a truthy value) will poll file size, holding its add
and change
events until the size does not change for a configurable amount of time.
$ lerna watch --await-write-finish -- <command>
--awf-poll-interval
Default to 100
, file size polling interval, in milliseconds.
$ lerna watch --awf-poll-interval=100 -- <command>
--awf-stability-threshold
Default to 2000
, amount of time in milliseconds for a file size to remain constant before emitting its event.
$ lerna watch --awf-stability-threshold=2000 -- <command>
Watch Environment Variables
Lerna will set 3 separate environment variables when running the inner command. These can be used to customize the command that is run.
-
$LERNA_PACKAGE_NAME
will be replaced with the name of the package that changed. -
$LERNA_FILE_CHANGES
will be replaced with the file(s) that changed, separated by whitespace when multiple files are changed.
Note When using these variables in the shell, you will need to escape the
$
with a backslash (\
). See the examples above.
Running With Package Managers
The examples above showcase using lerna
directly in the terminal. However, you can also use lerna
via a package manager without adding it to your path:
pnpm:
pnpm lerna watch -- lerna run build --scope=\$LERNA_PACKAGE_NAME
yarn:
yarn lerna -- watch -- lerna run build --scope=\$LERNA_PACKAGE_NAME
npx:
npx -c 'lerna watch -- lerna run build --scope=\$LERNA_PACKAGE_NAME'
Note When using
npx
, you will need to use-c
and surround the entirelerna watch
command in single quotes ('
). Without this,npx
will try to replace the watch environment variables before passing the command tolerna
, resulting in an always empty value for$LERNA_PACKAGE_NAME
and$LERNA_FILE_CHANGES
.