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
- No need to pass --config anymore
- dot reporters: dynamic dependencies show up as dotted lines
- Performance improvements
- Breaking changes
- breaking for both CLI and API
- BREAKING: Dropped support for node 14
- BREAKING: Dropped support for yarn 1 plug'n play
- BREAKING: Not passing --config now means 'use default configuration file'
- BREAKING: For glob patterns on windows use forward slashes
- breaking: API only
- BREAKING: API is ESM only
- BREAKING: API is async
- BREAKING: cruise signature change
- breaking for both CLI and API
🔏 shasum of the package as published on npmjs: 4ece1a93c4e954f30350cbb99fd62497cb705e51
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
.
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.
#795: lazy loading own code: (-100ms)
- 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.
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 change
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.
See example to call cruise
below to see how a call could look right now.
Example call to cruise
Before:
import { cruise } from 'dependency-cruiser';
import extractDepcruiseConfig from "dependency-cruiser/config-utl/extract-depcruise-config";
import extractTSConfig from "dependency-cruiser/config-utl/extract-ts-config";
import extractWebpackResolveConfig from "dependency-cruiser/config-utl/extract-webpack-resolve-config"
import extractBabelConfig from "dependency-cruiser/config-utl/extract-babel-config";
const lCruiseOptions = {
// ...
};
const lResult = cruise(
["src", "test"],
await extractDepcruiseConfig("./.dependency-cruiser.js"),
extractWebpackResolveConfig("webpack.config.js"),
extractTSConfig("./tsconfig.json"),
// not possible to pass a babel configuration
}
);
After:
import { cruise } from "dependency-cruiser";
import extractDepcruiseConfig from "dependency-cruiser/config-utl/extract-depcruise-config";
import extractTSConfig from "dependency-cruiser/config-utl/extract-ts-config";
import extractWebpackResolveConfig from "dependency-cruiser/config-utl/extract-webpack-resolve-config";
import extractBabelConfig from "dependency-cruiser/config-utl/extract-babel-config";
const lResult = await cruise(
["src", "test"],
await extractDepcruiseConfig("./.dependency-cruiser.js"),
await extractWebpackResolveConfig("webpack.config.js"),
{
tsConfig: extractTSConfig("./tsconfig.json"),
babelConfig: await extractBabelConfig("./babel.conf.json"),
}
);
List of changes
- 5a62d73 chore(lint): disables exports-last rule
- a5c2bb5 feature(progress): some more tweaks to the usability of the performance-log
- 9329ae4 build(npm): updates external dependencies
- faaadea chore: replaces references to the develop branch with main
- 145527d doc(cache): adds tsdoc & checks on it
- cfb8254 chore: replaces references to the master branch with develop
- 56fd111 chore(ci): removes v13 as integration branch and adds main
- b092d70 fix(types): adds mainFields and mainFiles to the enhancedResolveOptions in ICruiseOptions
- 4556fe3 fix(enrich): adds used tsconfig to options used + adds it & babelConfig, webpackConfig to IConfiguration type (#805)
- 8bac684 doc(report): corrects description of the null reporter
- 7cb21dd 13.0.0-beta-7
- 4fdaf68 perf(extract): splits transpiler availability from execution (#804)
- ecd5563 fix(schema|types): adds null reporter to schema and types
- 5d62d58 fix(schema|types): adds 'checksum' attribute to the module schema (#803)
- 2380954 doc(progress): copy edit of the first step
- df0267d 13.0.0-beta-6
- d4d6f7c refactor(cache): makes git operations in metadata-strategy async
- d408208 refactor(cache): makes read and write async
- 78e6f6f build(npm): updates external dependencies
- 115ec7b refactor(progress): improves progress logging DX
- c1c0fea bugfix(cache): handles empty known violations arrays
- 220e0a3 13.0.0-beta-5
- 8d23c9e doc(extract): improves typing of the meta interface
- 00965ee refactor(config-utl): makes babel json5 configs and known violations read async as well
- 52f5fa0 bugfix(enrich): removes superfluous trailing argument
- bea4ce6 chore: makes yarn --silent by default
- 4e57f89 feature(progress): adds visual aides to performance-log listener
- 72ce164 feature(report): adds a 'null' reporter (#802)
- 12738f5 feature(report): in dot reporters, by default makes dynamic dependencies dashed lines (#801)
- fc6119f perf(main): splits off cruise & format in their own modules (#800)
- 68526f3 doc: makes readme backwards compatible (#799)
- 307c307 perf(cli): reads webpack, typescript and babel config options in parallel (#797)
- 8a89bd8 refactor(wrap-stream-in-html): read template elements asynchronously
- a4063bc 13.0.0-beta-4
- 44c3428 build(npm): updates external dependencies
- 7611a4f perf(cli|main): lazy loads config mangling, extract and enrich steps (#796)
- 2fea498 perf(cli|report): lazy loads --init, reporter and caching code (#795)
- a64ca14 13.0.0-beta-3
- 4a36b7f ci: snoozes node 'this is experimental' warnings for esm c.s.
- b8f898a doc(extract): document why we're using 'reduces' instead of a 'maps' while gathering initial sources
- 6e14233 build(npm): updates external dependencies
- 4b47220 chore(test): sets mocha reporter to 'dot'
- b745685 chore(ci): replaces node 19 with node 20
- 2a7e7ce 13.0.0-beta-2
- 1ec9e34 build(npm): update external dependencies
- 947fb34 refactor(report): makes csv reporter less OS dependent (#793)
- 290923b feature(config-utl): enables webpack configurations in ESM format (#792)
- cd7eff7 refactor(cli): replaces deprecated substr with substring
- 521ffe0 chore: removes commonjs remnants (#791)
- d46f5d2 refactor: uses qualified imports for imports from node native modules (#790)
- b4f7e25 13.0.0-beta-1
- 0dc39fd fix(tools): makes sample and fixture generators work with the new interfaces
- 96f7ac0 build(npm): update external dependencies
- 9041d03 refactor(extract): converts svelte helper to esm
- 70008e2 refactor(utl): converts to esm (#789)
- 13ae375 refactor(graph-utl): converts to esm (#788)
- 8c78331 refactor(validate): converts to esm (#787)
- 892cfa5 refactor(enrich): converts to esm (#786)
- 1adefbe doc(report): changes copy of instructions what to do with ignored violations
- 912892d refactor(extract): converts svelte wrapper to esm (#785)
- 3c16e7d refactor(cli): converts hbs calling code in init-config to esm (#783)
- 3c8c1d6 refactor(report): converts to esm (#782)
- e33a80f bugfix: lets several tools ignore the newly named and generated json-schemas-as-esm
- a8872a0 bugfix(npm): sets main to the renamed main/index module
- f4ca4df refactor(tools): converts the generated json schema's to esm (#781)
- 9f794e7 refactor(main): converts to esm (#780)
- c311f8b chore: updates c8 configuration to renamed files
- b5e2ab1 refactor(report): converts RE for reporter plugins to something more readable
- 89a03fd refactor(cache): converts to esm (#779)
- 77b7424 refactor: uses node: protocol for all node native module imports (#778)
- ce077a7 refactor(extract): removes default export from meta (#777)
- 411adf7 refactor(extract): moves utl/* into one helpers.mjs (#776)
- 6c7de70 refactor(extract): moves get-manifest (#775)
- dc211d0 refactor(extract): converts to esm (#774)
- e1a61cd refactor: replaces cruise function with signature from futureCruise BREAKING (#773)
- 701e020 chore(config-utl): converts to esm (#772)
- 12963a9 feature(cli): removes the necessity to pass --config to read the deafult configuration file BREAKING (#771)
- 822afeb chore(cli): converts to esm (#765)
- 1b5c929 build(npm): bumps glob to latest BREAKING (#770)
- 7e354f6 chore: de-supports node 14 BREAKING
- 687f9fc chore(ci): adds the v13 branch to the ones to check all the things on
- 9ec0025 chore: de-support yarn PnP version 1 BREAKING (#769)