knip 0.7.1 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +99 -58
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,31 +1,34 @@
1
1
  # ✂️ Knip
2
2
 
3
3
  Knip scans your JavaScript and TypeScript projects for **unused files, dependencies and exports**: things that can be
4
- removed! Less code means better performance and less to maintain, important for both UX and DX!
5
-
6
- For comparison, ESLint finds unused variables inside files in isolation, but this will not be flagged:
4
+ removed! Less code leads to improved performance, less maintenance, easier refactorings.
7
5
 
8
6
  ```ts
9
7
  export const myVar = true;
10
8
  ```
11
9
 
12
- Unused files will also not be detected by ESLint. So how do you know which files, dependencies and exports are no longer
13
- used? This requires an analysis of all the right files in the project.
10
+ ESLint handles files in isolation, so the `export` keyword "blocks" further analysis. Unused files and dependencies will
11
+ also not be detected. You could think of Knip as going (far!) beyond the "unused variable" rule of ESLint. Knip lints
12
+ the project as a whole, or parts of it.
14
13
 
15
- This is where Knip comes in:
14
+ It's only human to forget to delete files or dependencies that you no longer use. How to keep track of how many times
15
+ something is actually used in a codebase? How to find out this number just dropped to zero for anything? Where to even
16
+ start finding things that can be removed during maintenance and refactorings? Especially in larger projects all of this
17
+ can be tedious. This is where Knip comes in.
16
18
 
17
- - [x] Resolves all (unused) files in your project and reports **unused files, dependencies and exports**.
18
- - [x] Verifies that exported symbols are actually used in other files, even when part of an imported namespace.
19
+ Boring stuff should be automated! Just let Knip have a crack at it:
20
+
21
+ - [x] Finds **unused files, dependencies and exports**.
19
22
  - [x] Finds dependencies not listed in `package.json`.
23
+ - [x] Verifies that exported symbols are actually used in other files, even when part of an imported namespace.
24
+ - [x] Supports JavaScript inside TypeScript projects (`"allowJs": true`).
20
25
  - [x] Finds duplicate exports of the same symbol.
21
- - [x] Supports JavaScript inside TypeScript projects (`"allowJs": true`)
22
- - [x] Supports JavaScript-only projects using ESM (without a `tsconfig.json`)
26
+ - [x] Supports JavaScript ES Module-based projects without a `tsconfig.json`.
23
27
  - [x] Features multiple [reporters](#reporters) and supports [custom reporters](#custom-reporters).
24
28
 
25
- Knip really shines in larger projects where you have non-production files (such as `/docs`, `/tools` and `/scripts`).
26
- The `includes` setting in `tsconfig.json` is often too broad, resulting in too many false negatives. To produce good
27
- results it's essential to configure entry files. A comparison with similar toos answers the question
28
- [Why yet another unused file/dependency/export finder?](#why-yet-another-unused-filedependencyexport-finder)
29
+ Knip really shines in larger projects. A little bit of configuration will pay off, I promise. A comparison with similar
30
+ tools answers the question
31
+ [why another unused file/dependency/export finder?](#why-yet-another-unused-filedependencyexport-finder)
29
32
 
30
33
  Knip is a fresh take on keeping your projects clean & tidy!
31
34
 
@@ -38,6 +41,8 @@ Knip is a fresh take on keeping your projects clean & tidy!
38
41
  npm install -D knip
39
42
  ```
40
43
 
44
+ Knip requires least Node.js v16.17 or v18 is required. Knip is _cutting edge!_
45
+
41
46
  ## Usage
42
47
 
43
48
  Create a configuration file, let's give it the default name `knip.json` with these contents:
@@ -73,8 +78,6 @@ Knip works by creating two sets of files:
73
78
 
74
79
  ![How it works](./assets/how-it-works.drawio.svg)
75
80
 
76
- Please read on if you think you have too many results: [too many false positives?](#too-many-false-positives)
77
-
78
81
  ## Options
79
82
 
80
83
  ```
@@ -120,16 +123,17 @@ following groups of issues:
120
123
 
121
124
  - `files` - Unused files: did not find references to this file
122
125
  - `dependencies` - Unused dependencies: did not find references to this dependency
123
- - `unlisted` - Unlisted dependencies: this dependency is used, but not listed in package.json (1)
126
+ - `unlisted` - Unlisted dependencies: imported dependencies, but not listed in package.json (1)
124
127
  - `exports` - Unused exports: did not find references to this exported variable
125
128
  - `nsExports` - Unused exports in namespaces: did not find direct references to this exported variable (2)
126
129
  - `types` - Unused types: did not find references to this exported type
127
130
  - `nsTypes` - Unused types in namespaces: did not find direct references to this exported variable (2)
128
- - `duplicates` - Duplicate exports: the same thing is exported more than once with different names
131
+ - `duplicates` - Duplicate exports: the same thing is exported more than once with different names from the same file
129
132
 
130
133
  Each group type can be an `--include` or `--exclude` to slice & dice the report to your needs.
131
134
 
132
- 1. This may also include dependencies that could not be resolved properly, such as `local/dir/file.ts`.
135
+ 1. This may also include dependencies that could not be resolved properly (such as non-relative `local/dir/file.ts` not
136
+ and `local` not being in `node_modules`).
133
137
  2. The variable or type is not referenced directly, and has become a member of a namespace. That's why Knip is not sure
134
138
  whether this export can be removed, so please look into it:
135
139
 
@@ -140,26 +144,41 @@ As always, make sure to backup files or use Git before deleting files or making
140
144
  - Unused files can be deleted.
141
145
  - Unused dependencies can be removed from `package.json`.
142
146
  - Unlisted dependencies should be added to `package.json`.
143
- - Unused exports and types: remove the `export` keyword in front of unused exports. Then you (or tools such as ESLint)
144
- can see whether the variable or type is used within its own file. If this is not the case, it can be removed.
147
+ - Unused exports and types: remove the `export` keyword in front of unused exports. Then you (or tools such as the
148
+ TypeScript language server in VS Code and/or ESLint) can see whether the variable or type is used within the same
149
+ file. If this is not the case, it can be removed.
150
+
151
+ 🔁 Repeat the process to reveal new unused files and exports. Sometimes it's so liberating to delete things!
152
+
153
+ ## Production versus non-production code
154
+
155
+ Feels like you're getting too many false positives? Let's talk about `entryFiles` and `projectFiles`.
156
+
157
+ ### Production code
145
158
 
146
- 🔁 Repeat the process to reveal new unused files and exports. Sometimes it's so liberating to delete things.
159
+ The default configuration for Knip is very strict and targets production code. Non-production files such as tests should
160
+ not be part of the `entryFiles`. Here's why: test and other non-production files often import production files, which
161
+ will prevent the production files from being reported as unused. For best results:
147
162
 
148
- ## Too many false positives?
163
+ - Include only production entry files to the `entryFiles`.
164
+ - Include only and all production files to the `projectFiles`.
165
+ - If necessary, exclude non-production files from the `projectFiles` (using negation patterns).
149
166
 
150
- The default configuration for Knip is very strict and targets production code. For best results, it is recommended to
151
- exclude files such as tests from the project files. Here's why: when including tests and other non-production files,
152
- they may import production files, which will prevent them from being reported as unused.
167
+ This will ensure Knip understands what production code can be removed.
153
168
 
154
- Excluding non-production files from the `projectFiles` allows Knip to understand what production code can be removed
155
- (including dependent files!).
169
+ ### Non-production code
156
170
 
157
- Non-production code includes files such as end-to-end tests, tooling, scripts, Storybook stories, etc.
171
+ Non-production code includes files such as unit tests, end-to-end tests, tooling, scripts, Storybook stories, etc. Think
172
+ of it the same way as the convention to split `dependencies` and `devDependencies` in `package.json`.
158
173
 
159
- Think of it the same way as you would split `dependencies` and `devDependencies` in `package.json`.
174
+ To analyze the project as a whole:
160
175
 
161
- To include both production and test files to analyze the project as a whole, include both sets of files to `entryFiles`,
162
- and add `dev: true` to a file named such as `knip.dev.json`:
176
+ - Include both production entry files and test files to the `entryFiles`.
177
+ - Include all production files to the `projectFiles`.
178
+ - Include non-production files from the `projectFiles`.
179
+ - To include `devDependencies`, set `dev: true` in the configuration or add `--dev` as a command line flag.
180
+
181
+ Here's an example:
163
182
 
164
183
  ```json
165
184
  {
@@ -169,7 +188,7 @@ and add `dev: true` to a file named such as `knip.dev.json`:
169
188
  }
170
189
  ```
171
190
 
172
- Now use `-c knip.dev.json` to find unused files and exports for the combined set of files as configured in `entryFiles`.
191
+ Now use `-c knip.dev.json` to find unused files, dependencies and exports for the project as a whole.
173
192
 
174
193
  An alternative way to store `dev` configuration is in this example `package.json`:
175
194
 
@@ -190,7 +209,9 @@ An alternative way to store `dev` configuration is in this example `package.json
190
209
  }
191
210
  ```
192
211
 
193
- This way, the `--dev` flag will use the `dev` options (and also add `devDependencies` to the `dependencies` report).
212
+ Using the `--dev` flag will now switch to the non-production analysis.
213
+
214
+ Depending on the complexity of the project, be aware that it might require some fine-tuning on your end.
194
215
 
195
216
  ## More configuration examples
196
217
 
@@ -198,7 +219,7 @@ This way, the `--dev` flag will use the `dev` options (and also add `devDependen
198
219
 
199
220
  #### Separate packages
200
221
 
201
- In repos with multiple (published) packages, the `--dir` option comes in handy. With similar package structures, the
222
+ In repos with multiple (publishable) packages, the `--dir` option comes in handy. With similar package structures, the
202
223
  packages can be configured using globs:
203
224
 
204
225
  ```json
@@ -212,7 +233,7 @@ packages can be configured using globs:
212
233
 
213
234
  Packages can also be explicitly configured per package directory.
214
235
 
215
- To scan the packages separately, using the first match from the configuration file:
236
+ To scan the packages separately, using the matching pattern from the configuration file:
216
237
 
217
238
  ```
218
239
  knip --dir packages/client
@@ -364,12 +385,11 @@ The owner of `package.json` is considered the owner of unused (dev) dependencies
364
385
 
365
386
  Use `--reporter-options '{"path":".github/CODEOWNERS"}'` to pass another location for the code owners file.
366
387
 
367
- ## Why Yet Another unused file/dependency/export finder?
388
+ ## Really, another unused file/dependency/export finder?
389
+
390
+ There are already some great packages available if you want to find unused dependencies OR unused exports.
368
391
 
369
- There are already some great packages available. Getting good results when finding unused files, dependencies and
370
- exports is not trivial. Repositories don't seem to get any smaller and with the rise of monorepos even more so. Tools
371
- like this need to analyze potentially many and/or large files, which is memory and time-consuming. Although I normally
372
- try to stick to the Unix philosophy, here I believe it's efficient to merge these issue reports into a single tool. When
392
+ Although I love the Unix philosophy, here I believe it's efficient to handle multiple concerns in a single tool. When
373
393
  building a dependency graph of the project, an abstract syntax tree for each file, and traversing all of this, why not
374
394
  collect the various issues in one go?
375
395
 
@@ -377,26 +397,45 @@ collect the various issues in one go?
377
397
 
378
398
  This table is a work in progress, but here's a first impression. Based on their docs (please report any mistakes):
379
399
 
380
- | Feature | **knip** | [depcheck][1] | [unimported][2] | [ts-unused-exports][3] | [ts-prune][4] | [find-unused-exports][5] |
381
- | --------------------------- | :--------: | :-----------: | :-------------: | :--------------------: | :-----------: | :----------------------: |
382
- | Unused files | | - | ✅ | - | - | - |
383
- | Unused dependencies | | ✅ | ✅ | - | - | - |
384
- | Unlisted dependencies | | ✅ | ✅ | - | - | - |
385
- | Custom dependency resolvers | ❌ [#7][6] | ✅ | (1) | - | - | - |
386
- | Unused exports | | - | - | ✅ | ✅ | ✅ |
387
- | Duplicate exports | | - | - | ❌ | ❌ | ❌ |
388
- | Search namespaces | | - | - | ✅ | ❌ | ❌ |
389
- | Custom reporters | | - | - | - | - | - |
390
- | Pure JavaScript/ESM | | ✅ | ✅ | - | - | ✅ |
391
- | Configure entry files | | ❌ | ✅ | ❌ | ❌ | ❌ |
392
- | Support monorepo | 🟠 (2) | - | - | - | - | - |
393
- | ESLint plugin available | - | - | - | ✅ | - | - |
400
+ | Feature | **knip** | [depcheck][1] | [unimported][2] | [ts-unused-exports][3] | [ts-prune][4] | [find-unused-exports][5] |
401
+ | -------------------------------- | :------: | :-----------: | :-------------: | :--------------------: | :-----------: | :----------------------: |
402
+ | Unused files | | - | ✅ | - | - | - |
403
+ | Unused dependencies | | ✅ | ✅ | - | - | - |
404
+ | Unlisted dependencies | | ✅ | ✅ | - | - | - |
405
+ | [Custom dependency resolvers][7] | ❌ | ✅ | | - | - | - |
406
+ | Unused exports | | - | - | ✅ | ✅ | ✅ |
407
+ | Duplicate exports | | - | - | ❌ | ❌ | ❌ |
408
+ | Search namespaces | | - | - | ✅ | ❌ | ❌ |
409
+ | Custom reporters | | - | - | - | - | - |
410
+ | Pure JavaScript/ESM | | ✅ | ✅ | - | - | ✅ |
411
+ | Configure entry files | | ❌ | ✅ | ❌ | ❌ | ❌ |
412
+ | [Support monorepos][8] | 🟠 | - | - | - | - | - |
413
+ | ESLint plugin available | - | - | - | ✅ | - | - |
394
414
 
395
415
  ✅ = Supported, ❌ = Not supported, - = Out of scope
396
416
 
397
- 1. unimported is strict and works based on production files and `dependencies`, so does not have custom dependency
398
- resolvers which are usually only needed for `devDependencies`.
399
- 2. knip wants to [support monorepos](#monorepos) properly, the first steps in this direction are implemented.
417
+ ## Monorepos
418
+
419
+ Knip wants to [support monorepos](#monorepos) properly, the first steps in this direction are implemented.
420
+
421
+ ## Custom dependency resolvers
422
+
423
+ Using a string like `"plugin:cypress/recommended"` in the `extends` property of a `.eslintrc.json` in a package
424
+ directory of a monorepo is nice for DX. But Knip will need some help to find it and to understand this _resolves to_ the
425
+ `eslint-plugin-cypress` _dependency_. Or see it is not listed in `package.json`. Or that the dependency is still listed,
426
+ but no longer in use. Many popular projects reference plugins in similar ways, such as Babel, Webpack and Storybook.
427
+
428
+ Big compliments to [depcheck](https://github.com/depcheck/depcheck#special) which already does this! They call this
429
+ "specials". [Knip has this ambition][6], too.
430
+
431
+ unimported is strict in this regard and works based on production files and `dependencies`, so does not have custom
432
+ dependency resolvers which are usually only needed for `devDependencies`.
433
+
434
+ ## TypeScript language services
435
+
436
+ TypeScript language services could play a major role in most of the "unused" areas, as they have an overview of the
437
+ project as a whole. For instance, this powers the "Find references" feature in VS Code. I think features like "duplicate
438
+ exports" or "custom dependency resolvers" are userland territory, much like code linters.
400
439
 
401
440
  ## Knip?!
402
441
 
@@ -409,3 +448,5 @@ for the job. I'm motivated to make knip perfectly suited for the job of cutting
409
448
  [4]: https://github.com/nadeesha/ts-prune
410
449
  [5]: https://github.com/jaydenseric/find-unused-exports
411
450
  [6]: https://github.com/webpro/knip/issues/7
451
+ [7]: #custom-dependency-resolvers
452
+ [8]: #monorepos-1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
4
4
  "description": "Find unused files, dependencies and exports in your TypeScript and JavaScript project",
5
5
  "keywords": [
6
6
  "find",