knip 0.7.0 → 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.
- package/README.md +99 -58
- package/dist/reporters/codeowners.js +1 -1
- package/package.json +4 -4
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
|
|
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
|
-
|
|
13
|
-
|
|
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
|
-
|
|
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
|
-
|
|
18
|
-
|
|
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
|
|
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
|
|
26
|
-
|
|
27
|
-
|
|
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
|

|
|
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:
|
|
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
|
|
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
|
|
144
|
-
can see whether the variable or type is used within
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
174
|
+
To analyze the project as a whole:
|
|
160
175
|
|
|
161
|
-
|
|
162
|
-
|
|
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
|
|
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
|
-
|
|
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 (
|
|
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
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
|
381
|
-
|
|
|
382
|
-
| Unused files
|
|
383
|
-
| Unused dependencies
|
|
384
|
-
| Unlisted dependencies
|
|
385
|
-
| Custom dependency resolvers
|
|
386
|
-
| Unused exports
|
|
387
|
-
| Duplicate exports
|
|
388
|
-
| Search namespaces
|
|
389
|
-
| Custom reporters
|
|
390
|
-
| Pure JavaScript/ESM
|
|
391
|
-
| Configure entry files
|
|
392
|
-
| Support
|
|
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
|
-
|
|
398
|
-
|
|
399
|
-
|
|
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
|
|
@@ -32,7 +32,7 @@ const logIssueGroupResults = (issues, cwd, title) => {
|
|
|
32
32
|
exports.default = ({ report, issues, cwd, isDev, options }) => {
|
|
33
33
|
let opts = {};
|
|
34
34
|
try {
|
|
35
|
-
opts = JSON.parse(options);
|
|
35
|
+
opts = options ? JSON.parse(options) : opts;
|
|
36
36
|
}
|
|
37
37
|
catch (error) {
|
|
38
38
|
console.error(error);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "knip",
|
|
3
|
-
"version": "0.7.
|
|
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",
|
|
@@ -45,14 +45,14 @@
|
|
|
45
45
|
"is-builtin-module": "3.2.0",
|
|
46
46
|
"micromatch": "4.0.5",
|
|
47
47
|
"ts-morph": "16.0.0",
|
|
48
|
-
"ts-morph-helpers": "0.5.
|
|
48
|
+
"ts-morph-helpers": "0.5.1"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/micromatch": "4.0.2",
|
|
52
|
-
"@types/node": "18.8.
|
|
52
|
+
"@types/node": "18.8.5",
|
|
53
53
|
"prettier": "2.7.1",
|
|
54
54
|
"release-it": "15.5.0",
|
|
55
|
-
"tsx": "3.
|
|
55
|
+
"tsx": "3.10.1",
|
|
56
56
|
"typescript": "4.8.4"
|
|
57
57
|
},
|
|
58
58
|
"release-it": {
|