You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Support for ESM in dependency-cruiser, babel and webpack configurations
As dependency-cruiser itself is now written in ESM, it can now also read .dependency-cruiser, babel and webpack configurations in ESM, so you can write them in more modern JavaScript if you want to. Previously supported formats (commonjs, json5 etc) remain supported
No need to pass --config anymore
In previous versions, even when you had a dependency-cruiser configuration with one of the default names, you still need to pass --config on the command line to tell it to use that configuration. As of version 13 this is not necessary anymore. Otherwise, the --config option still work as it did before.
If you want to run the dependency-cruiser CLI without a configuration file you'll have to explicitly pass it --no-config.
Let me know if you do! I'm interested in these use cases.
dot reporters: dynamic dependencies show up as dotted lines
This was already possible - in v13, we've made it the default as it proved useful to distinguish dynamic imports from regular ones. See #801 for details.
Performance improvements
When I converted dependency-cruiser from commonjs to ESM (on node 19) it turned out dependency-cruiser's self scan took longer than it did before the conversion. Dependency-cruiser's performance-log and closer analysis with node --cpu-prof showed that most of the extra time was added at startup time, importing modules. Because I set myself as a goal to have v13 at least as fast as v12 I took a closer look at what was loaded, that might not be necessary at startup.
typically you only run dependency-cruiser with one reporter at a time. Because we're using static imports, however, all reporters were loaded, some of which are reasonably large - taking import parse time. By dynamically importing only the one reporter we need, and only when we needed it we shaved of ~40ms from the startup time.
After having run --init once, you're not going to need it anymore. The init code was statically imported, though. Dynamically importing it only when --init was engaged shaved off ~40ms of regular startup time.
If you don't run with caching (you should, it's awesome) - caching code shouldn't be imported either - lazy loading that saves ~20ms.
defer loading analytical modules (-100ms - -700ms for cache only runs)
I also realized dependency-cruiser's serving 100% from cache scenario hardly needs to run any static analysis code. Lazy loading these modules till after we've established we need them shaves off ~100ms - ~700ms from 100% from cache runs. The 700ms is extreme though - it's because in dependency-cruiser's self scan babel, vue, svelte, typescript, swc and even coffeescript are available at the same time. I pity you if your real live project has this as well...
It is possible to go deeper here and lazy load the individual transpilers as well, making dependency-cruiser's self-scan nice and fast but the gain in practical situations (where you have only one or two of them in place) would be limited, unless there's a transpiler installed you don't use in your setup (but e.g. only have because a devDependency has it - babel is a logical candidate for this). This improvement might come in a future version of dependency-cruiser.
Breaking changes: CLI and API
Dropped support for node 14
Nodejs 14 is end of life by the end of April 2023 (source). This will mean that most projects will by then have moved to higher versions. If you can't move to nodejs 14 you can keep using dependency-cruiser v12 for a while.
Dropped support for yarn 1 plug'n play
Yarn 1 is still nominally maintained - the yarn team encourages everyone to migrate to yarn 3, which is now maintained for a longer time than yarn 1 ever was. While yarn 1 itself still works fantastically, its pnp implementation won't keep up with new developments in the node landscape (e.g. the node: prefix doesn't work, ES modules don't work) - they do work in later versions of yarn, so if you're still on yarn 1 with PnP you probably want to upgrade to yarn 3 anyway.
To be clear:
dependency-cruiser >= v13 still works with yarn 3 (and 2) plug'n play . We actively maintain an integration test to ensure it keeps doing so.
depencency-cruiser >= v13 will keep running in yarn 1 installations that don't have plug'n play engaged. Even if PnP is engaged, it probably would still work when you 'eject' dependency-cruiser from PnP.
dependency-cruiser <= v12 will still run with yarn 1 + PnP
Not passing --config now means 'use default configuration file'
In previous versions, even when you had a dependency-cruiser configuration with one of the default names, you still need to pass --config on the command line to tell it to use that configuration. This was confusing to many because it's different from most other tools out there in the same space do it.
As of version 13 this is not necessary anymore to pass a --config option to read the default configuration. Otherwise, the --config option still work as it did before.
If you want to run the dependency-cruiser CLI without a configuration file you'll have to explicitly pass it --no-config.
Let me know if you do! I'm interested in these use cases.
Dependency-cruiser is now implemented in ESM - which means that it can only be called from ESM code anymore. I've been looking for ways to compile it down to commonjs, but the transpiler chains I've tried so far can't (e.g. by refusing to convert top level awaits).
API is async (cruise, format, config-utl)
Because in ESM (dynamically) importing modules is an asynchronous affair, all dependency-cruiser interfaces that weren't already had to become asynchronous as well, with the exception of the configuration utility to extract TypeScript configurations.
Apart from becoming asynchronous, we've rationalised the parameters to cruise. In the old interface the fourth parameter was reserved to passing a (normalized) TypeScript configuration only, while having no room to pass a babel configuration or any other (future) transpilation configuration.
The new interface makes the fourth parameter an object that can take a tsConfig, a babelConfig, or both of them.
import{cruise}from'dependency-cruiser';importextractDepcruiseConfigfrom"dependency-cruiser/config-utl/extract-depcruise-config";importextractTSConfigfrom"dependency-cruiser/config-utl/extract-ts-config";importextractWebpackResolveConfigfrom"dependency-cruiser/config-utl/extract-webpack-resolve-config"importextractBabelConfigfrom"dependency-cruiser/config-utl/extract-babel-config";constlCruiseOptions={// ...};constlResult=cruise(["src","test"],awaitextractDepcruiseConfig("./.dependency-cruiser.js"),extractWebpackResolveConfig("webpack.config.js"),extractTSConfig("./tsconfig.json"),// not possible to pass a babel configuration});
To keep dependency-cruiser future proof (and sweeter to use) it was necessary to make some breaking changes in v13.
Most of the breaking changes impact only the API/ library. We've worked hard to avoid it, but some affect the CLI as well.
Summary
Improvements
Support for ESM in dependency-cruiser, babel and webpack configurations
As dependency-cruiser itself is now written in ESM, it can now also read .dependency-cruiser, babel and webpack configurations in ESM, so you can write them in more modern JavaScript if you want to. Previously supported formats (commonjs, json5 etc) remain supported
No need to pass --config anymore
In previous versions, even when you had a dependency-cruiser configuration with one of the default names, you still need to pass
--config
on the command line to tell it to use that configuration. As of version 13 this is not necessary anymore. Otherwise, the--config
option still work as it did before.If you want to run the dependency-cruiser CLI without a configuration file you'll have to explicitly pass it
--no-config
.dot reporters: dynamic dependencies show up as dotted lines
This was already possible - in v13, we've made it the default as it proved useful to distinguish dynamic imports from regular ones. See #801 for details.
Performance improvements
When I converted dependency-cruiser from commonjs to ESM (on node 19) it turned out dependency-cruiser's self scan took longer than it did before the conversion. Dependency-cruiser's performance-log and closer analysis with node --cpu-prof showed that most of the extra time was added at startup time, importing modules. Because I set myself as a goal to have v13 at least as fast as v12 I took a closer look at what was loaded, that might not be necessary at startup.
#795: lazy loading own code: (-100ms)
defer loading analytical modules (-100ms - -700ms for cache only runs)
I also realized dependency-cruiser's serving 100% from cache scenario hardly needs to run any static analysis code. Lazy loading these modules till after we've established we need them shaves off ~100ms - ~700ms from 100% from cache runs. The 700ms is extreme though - it's because in dependency-cruiser's self scan babel, vue, svelte, typescript, swc and even coffeescript are available at the same time. I pity you if your real live project has this as well...
It is possible to go deeper here and lazy load the individual transpilers as well, making dependency-cruiser's self-scan nice and fast but the gain in practical situations (where you have only one or two of them in place) would be limited, unless there's a transpiler installed you don't use in your setup (but e.g. only have because a devDependency has it - babel is a logical candidate for this). This improvement might come in a future version of dependency-cruiser.
Breaking changes: CLI and API
Dropped support for node 14
Nodejs 14 is end of life by the end of April 2023 (source). This will mean that most projects will by then have moved to higher versions. If you can't move to nodejs 14 you can keep using dependency-cruiser v12 for a while.
Dropped support for yarn 1 plug'n play
Yarn 1 is still nominally maintained - the yarn team encourages everyone to migrate to yarn 3, which is now maintained for a longer time than yarn 1 ever was. While yarn 1 itself still works fantastically, its pnp implementation won't keep up with new developments in the node landscape (e.g. the
node:
prefix doesn't work, ES modules don't work) - they do work in later versions of yarn, so if you're still on yarn 1 with PnP you probably want to upgrade to yarn 3 anyway.To be clear:
Not passing --config now means 'use default configuration file'
In previous versions, even when you had a dependency-cruiser configuration with one of the default names, you still need to pass
--config
on the command line to tell it to use that configuration. This was confusing to many because it's different from most other tools out there in the same space do it.As of version 13 this is not necessary anymore to pass a --config option to read the default configuration. Otherwise, the
--config
option still work as it did before.If you want to run the dependency-cruiser CLI without a configuration file you'll have to explicitly pass it
--no-config
.For glob patterns on windows use forward slashes
We've bumped to the most recent version of node-glob which has a breaking change where it doesn't accept
\
as path separators anymore - and instead advises to use forward slashes (/
) in stead.API only
API is ESM only
Dependency-cruiser is now implemented in ESM - which means that it can only be called from ESM code anymore. I've been looking for ways to compile it down to commonjs, but the transpiler chains I've tried so far can't (e.g. by refusing to convert top level awaits).
API is async (cruise, format, config-utl)
Because in ESM (dynamically) importing modules is an asynchronous affair, all dependency-cruiser interfaces that weren't already had to become asynchronous as well, with the exception of the configuration utility to extract TypeScript configurations.
For an example - see Example to call
cruise
.cruise
signature changeApart from becoming asynchronous, we've rationalised the parameters to
cruise
. In the old interface the fourth parameter was reserved to passing a (normalized) TypeScript configuration only, while having no room to pass a babel configuration or any other (future) transpilation configuration.The new interface makes the fourth parameter an object that can take a tsConfig, a babelConfig, or both of them.
See example to call
cruise
below to see how a call could look right now.Example call to
cruise
Before:
After:
List of changes
The text was updated successfully, but these errors were encountered: