treeshake-check 1.0.0
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/LICENSE +21 -0
- package/README.md +178 -0
- package/bin/treeshake-check.js +3 -0
- package/dist/analyzers/barrel.d.ts +6 -0
- package/dist/analyzers/barrel.d.ts.map +1 -0
- package/dist/analyzers/barrel.js +124 -0
- package/dist/analyzers/barrel.js.map +1 -0
- package/dist/analyzers/exports.d.ts +6 -0
- package/dist/analyzers/exports.d.ts.map +1 -0
- package/dist/analyzers/exports.js +192 -0
- package/dist/analyzers/exports.js.map +1 -0
- package/dist/analyzers/module-type.d.ts +6 -0
- package/dist/analyzers/module-type.d.ts.map +1 -0
- package/dist/analyzers/module-type.js +163 -0
- package/dist/analyzers/module-type.js.map +1 -0
- package/dist/analyzers/side-effects.d.ts +10 -0
- package/dist/analyzers/side-effects.d.ts.map +1 -0
- package/dist/analyzers/side-effects.js +203 -0
- package/dist/analyzers/side-effects.js.map +1 -0
- package/dist/bundlers/detector.d.ts +14 -0
- package/dist/bundlers/detector.d.ts.map +1 -0
- package/dist/bundlers/detector.js +100 -0
- package/dist/bundlers/detector.js.map +1 -0
- package/dist/bundlers/esbuild.d.ts +6 -0
- package/dist/bundlers/esbuild.d.ts.map +1 -0
- package/dist/bundlers/esbuild.js +142 -0
- package/dist/bundlers/esbuild.js.map +1 -0
- package/dist/bundlers/vite.d.ts +7 -0
- package/dist/bundlers/vite.d.ts.map +1 -0
- package/dist/bundlers/vite.js +195 -0
- package/dist/bundlers/vite.js.map +1 -0
- package/dist/bundlers/webpack.d.ts +6 -0
- package/dist/bundlers/webpack.d.ts.map +1 -0
- package/dist/bundlers/webpack.js +128 -0
- package/dist/bundlers/webpack.js.map +1 -0
- package/dist/cli/commands.d.ts +6 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +116 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +189 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +152 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# treeshake-check
|
|
2
|
+
|
|
3
|
+
A production-grade CLI tool to analyze JavaScript/TypeScript React applications for tree-shaking issues.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔍 **Auto-detect bundlers** - Vite, Webpack, Rollup, esbuild
|
|
8
|
+
- 🌳 **Barrel file analysis** - Detect `export *` patterns that break tree-shaking
|
|
9
|
+
- ⚠️ **Side effects detection** - Find top-level code that prevents dead code elimination
|
|
10
|
+
- 📦 **CommonJS detection** - Identify modules that don't tree-shake
|
|
11
|
+
- 📊 **Bundle stats parsing** - Analyze webpack stats.json, esbuild metafile, Vite/Rollup output
|
|
12
|
+
- 💡 **Fix suggestions** - Actionable recommendations for each issue
|
|
13
|
+
- 📋 **Multiple output formats** - Human-readable text or JSON for CI
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install -g treeshake-check
|
|
19
|
+
|
|
20
|
+
# Or use directly with npx
|
|
21
|
+
npx treeshake-check analyze
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
### Analyze a project
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Analyze current directory (auto-detect bundler)
|
|
30
|
+
treeshake-check analyze
|
|
31
|
+
|
|
32
|
+
# Analyze a specific directory
|
|
33
|
+
treeshake-check analyze ./my-react-app
|
|
34
|
+
|
|
35
|
+
# With specific bundler stats
|
|
36
|
+
treeshake-check analyze --stats dist/stats.json
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### CLI Options
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
treeshake-check analyze [path] [options]
|
|
43
|
+
|
|
44
|
+
Options:
|
|
45
|
+
-b, --bundler <type> Force bundler type (vite|webpack|rollup|esbuild)
|
|
46
|
+
-s, --stats <file> Path to bundle stats/metafile
|
|
47
|
+
-o, --output <format> Output format (text|json) (default: "text")
|
|
48
|
+
-t, --threshold <bytes> Minimum size to report (default: "0")
|
|
49
|
+
--no-suggestions Hide fix suggestions
|
|
50
|
+
-i, --include <patterns> Glob patterns to include
|
|
51
|
+
-e, --exclude <patterns> Glob patterns to exclude
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Generate bundle stats
|
|
55
|
+
|
|
56
|
+
#### Webpack
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
webpack --json > stats.json
|
|
60
|
+
treeshake-check analyze --stats stats.json
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
#### Vite/Rollup
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Install rollup-plugin-visualizer
|
|
67
|
+
npm install -D rollup-plugin-visualizer
|
|
68
|
+
|
|
69
|
+
# Configure in vite.config.ts
|
|
70
|
+
import { visualizer } from 'rollup-plugin-visualizer';
|
|
71
|
+
|
|
72
|
+
export default defineConfig({
|
|
73
|
+
plugins: [
|
|
74
|
+
visualizer({ filename: 'stats.json', json: true })
|
|
75
|
+
]
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
#### esbuild
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
// Enable metafile in build
|
|
83
|
+
await esbuild
|
|
84
|
+
.build({
|
|
85
|
+
entryPoints: ["src/index.ts"],
|
|
86
|
+
bundle: true,
|
|
87
|
+
metafile: true,
|
|
88
|
+
outfile: "dist/bundle.js",
|
|
89
|
+
})
|
|
90
|
+
.then((result) => {
|
|
91
|
+
fs.writeFileSync("meta.json", JSON.stringify(result.metafile));
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Example Output
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
🔍 Tree-Shaking Analysis Report
|
|
99
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
100
|
+
|
|
101
|
+
Summary:
|
|
102
|
+
📁 Project: /path/to/project
|
|
103
|
+
🔧 Bundler: vite
|
|
104
|
+
📊 Files Analyzed: 42
|
|
105
|
+
|
|
106
|
+
⚠️ Issues Found: 5
|
|
107
|
+
● Critical: 1
|
|
108
|
+
● High: 2
|
|
109
|
+
● Medium: 2
|
|
110
|
+
📦 Potential Savings: 85.3 KB
|
|
111
|
+
|
|
112
|
+
CRITICAL ISSUES
|
|
113
|
+
────────────────
|
|
114
|
+
1. CommonJS Module: node_modules/lodash/index.js
|
|
115
|
+
└─ Pattern: require('lodash')
|
|
116
|
+
└─ Impact: 72 KB
|
|
117
|
+
└─ lodash CommonJS bundle is included. Use lodash-es for tree-shaking.
|
|
118
|
+
└─ Fix: Switch to lodash-es
|
|
119
|
+
import { debounce } from 'lodash-es'
|
|
120
|
+
|
|
121
|
+
HIGH PRIORITY ISSUES
|
|
122
|
+
────────────────────
|
|
123
|
+
2. Wildcard Re-export: src/components/index.ts
|
|
124
|
+
└─ Line: 5
|
|
125
|
+
└─ Pattern: export * from './Button'
|
|
126
|
+
└─ Impact: 8.2 KB
|
|
127
|
+
└─ Wildcard re-export prevents tree-shaking.
|
|
128
|
+
└─ Fix: Use explicit named exports
|
|
129
|
+
export { Button } from './Button'
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## JSON Output
|
|
133
|
+
|
|
134
|
+
Use `--output json` for CI integration:
|
|
135
|
+
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"summary": {
|
|
139
|
+
"projectPath": "/path/to/project",
|
|
140
|
+
"bundler": "vite",
|
|
141
|
+
"totalIssues": 5,
|
|
142
|
+
"criticalCount": 1,
|
|
143
|
+
"highCount": 2,
|
|
144
|
+
"mediumCount": 2,
|
|
145
|
+
"lowCount": 0,
|
|
146
|
+
"estimatedSavings": 87347,
|
|
147
|
+
"analyzedFiles": 42
|
|
148
|
+
},
|
|
149
|
+
"issues": [
|
|
150
|
+
{
|
|
151
|
+
"type": "commonjs-module",
|
|
152
|
+
"severity": "critical",
|
|
153
|
+
"file": "node_modules/lodash/index.js",
|
|
154
|
+
"pattern": "require('lodash')",
|
|
155
|
+
"estimatedImpact": 72000,
|
|
156
|
+
"suggestion": {
|
|
157
|
+
"title": "Switch to lodash-es",
|
|
158
|
+
"code": "import { debounce } from 'lodash-es'"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Issue Types
|
|
166
|
+
|
|
167
|
+
| Type | Description |
|
|
168
|
+
| ---------------------------- | -------------------------------------------- |
|
|
169
|
+
| `barrel-file` | Barrel files with many re-exports |
|
|
170
|
+
| `wildcard-reexport` | `export *` patterns that include all exports |
|
|
171
|
+
| `side-effect` | Top-level code that runs on import |
|
|
172
|
+
| `commonjs-module` | CommonJS modules that don't tree-shake |
|
|
173
|
+
| `unused-export` | Exports not imported anywhere |
|
|
174
|
+
| `missing-sideeffects-config` | Missing `sideEffects` in package.json |
|
|
175
|
+
|
|
176
|
+
## License
|
|
177
|
+
|
|
178
|
+
MIT
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { TreeShakingIssue } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Analyzes files for barrel file patterns that can break tree-shaking
|
|
4
|
+
*/
|
|
5
|
+
export declare function analyzeBarrelFiles(files: string[], projectPath: string): Promise<TreeShakingIssue[]>;
|
|
6
|
+
//# sourceMappingURL=barrel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"barrel.d.ts","sourceRoot":"","sources":["../../src/analyzers/barrel.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,mBAAmB,CAAC;AAEzE;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EAAE,EACf,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAoB7B"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import * as acorn from "acorn";
|
|
2
|
+
import * as walk from "acorn-walk";
|
|
3
|
+
import { readFileSync } from "fs";
|
|
4
|
+
import { basename, relative } from "path";
|
|
5
|
+
/**
|
|
6
|
+
* Analyzes files for barrel file patterns that can break tree-shaking
|
|
7
|
+
*/
|
|
8
|
+
export async function analyzeBarrelFiles(files, projectPath) {
|
|
9
|
+
const issues = [];
|
|
10
|
+
for (const file of files) {
|
|
11
|
+
const fileName = basename(file);
|
|
12
|
+
// Only check index files (common barrel file pattern)
|
|
13
|
+
if (!fileName.match(/^index\.(js|ts|jsx|tsx|mjs|mts)$/)) {
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const content = readFileSync(file, "utf-8");
|
|
18
|
+
const fileIssues = analyzeBarrelContent(content, file, projectPath);
|
|
19
|
+
issues.push(...fileIssues);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// Skip files that can't be read
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return issues;
|
|
26
|
+
}
|
|
27
|
+
function analyzeBarrelContent(content, filePath, projectPath) {
|
|
28
|
+
const issues = [];
|
|
29
|
+
const relPath = relative(projectPath, filePath);
|
|
30
|
+
// Count re-exports to determine if this is a barrel file
|
|
31
|
+
let reexportCount = 0;
|
|
32
|
+
let wildcardReexportCount = 0;
|
|
33
|
+
const wildcardSources = [];
|
|
34
|
+
try {
|
|
35
|
+
const ast = acorn.parse(content, {
|
|
36
|
+
ecmaVersion: "latest",
|
|
37
|
+
sourceType: "module",
|
|
38
|
+
locations: true,
|
|
39
|
+
});
|
|
40
|
+
walk.simple(ast, {
|
|
41
|
+
ExportAllDeclaration(node) {
|
|
42
|
+
wildcardReexportCount++;
|
|
43
|
+
reexportCount++;
|
|
44
|
+
wildcardSources.push({
|
|
45
|
+
source: node.source?.value || "unknown",
|
|
46
|
+
line: node.loc?.start?.line || 0,
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
ExportNamedDeclaration(node) {
|
|
50
|
+
if (node.source) {
|
|
51
|
+
reexportCount++;
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Fall back to regex-based detection for files that fail to parse
|
|
58
|
+
const wildcardMatches = content.matchAll(/export\s+\*\s+from\s+['"]([^'"]+)['"]/g);
|
|
59
|
+
for (const match of wildcardMatches) {
|
|
60
|
+
wildcardReexportCount++;
|
|
61
|
+
reexportCount++;
|
|
62
|
+
const line = content.substring(0, match.index).split("\n").length;
|
|
63
|
+
wildcardSources.push({ source: match[1], line });
|
|
64
|
+
}
|
|
65
|
+
const namedReexportMatches = content.matchAll(/export\s+\{[^}]+\}\s+from\s+['"][^'"]+['"]/g);
|
|
66
|
+
for (const _match of namedReexportMatches) {
|
|
67
|
+
reexportCount++;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Only warn about barrel files with wildcard re-exports
|
|
71
|
+
if (wildcardReexportCount > 0) {
|
|
72
|
+
for (const { source, line } of wildcardSources) {
|
|
73
|
+
const severity = wildcardReexportCount > 3 ? "critical" : "high";
|
|
74
|
+
issues.push({
|
|
75
|
+
type: "wildcard-reexport",
|
|
76
|
+
severity,
|
|
77
|
+
file: relPath,
|
|
78
|
+
line,
|
|
79
|
+
pattern: `export * from '${source}'`,
|
|
80
|
+
description: `Wildcard re-export prevents tree-shaking. All exports from '${source}' will be included even if unused.`,
|
|
81
|
+
estimatedImpact: estimateWildcardImpact(source),
|
|
82
|
+
suggestion: {
|
|
83
|
+
title: "Use explicit named exports",
|
|
84
|
+
description: "Replace wildcard re-exports with explicit named exports to enable tree-shaking.",
|
|
85
|
+
code: `export { SpecificExport } from '${source}'`,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Warn about barrel files in general if they have many re-exports
|
|
91
|
+
if (reexportCount > 5 && wildcardReexportCount === 0) {
|
|
92
|
+
issues.push({
|
|
93
|
+
type: "barrel-file",
|
|
94
|
+
severity: "medium",
|
|
95
|
+
file: relPath,
|
|
96
|
+
pattern: `${reexportCount} re-exports in barrel file`,
|
|
97
|
+
description: `Large barrel file with ${reexportCount} re-exports. Some bundlers may include all modules when importing from this barrel.`,
|
|
98
|
+
estimatedImpact: reexportCount * 500, // Rough estimate
|
|
99
|
+
suggestion: {
|
|
100
|
+
title: "Consider direct imports",
|
|
101
|
+
description: "Import directly from source modules instead of through the barrel file.",
|
|
102
|
+
code: `import { Component } from './components/Component' // instead of './components'`,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return issues;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Estimate the bundle size impact of a wildcard re-export
|
|
110
|
+
*/
|
|
111
|
+
function estimateWildcardImpact(source) {
|
|
112
|
+
// Rough heuristics based on common patterns
|
|
113
|
+
if (source.includes("lodash"))
|
|
114
|
+
return 25000;
|
|
115
|
+
if (source.includes("icons") || source.includes("Icon"))
|
|
116
|
+
return 50000;
|
|
117
|
+
if (source.includes("utils") || source.includes("helpers"))
|
|
118
|
+
return 5000;
|
|
119
|
+
if (source.includes("components"))
|
|
120
|
+
return 10000;
|
|
121
|
+
// Default estimate
|
|
122
|
+
return 3000;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=barrel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"barrel.js","sourceRoot":"","sources":["../../src/analyzers/barrel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exports.d.ts","sourceRoot":"","sources":["../../src/analyzers/exports.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,gBAAgB,EAGjB,MAAM,mBAAmB,CAAC;AAO3B;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,MAAM,EAAE,EACf,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAiC7B"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import * as acorn from "acorn";
|
|
2
|
+
import * as walk from "acorn-walk";
|
|
3
|
+
import { readFileSync } from "fs";
|
|
4
|
+
import { relative, dirname, resolve } from "path";
|
|
5
|
+
/**
|
|
6
|
+
* Analyze exports to find unused ones
|
|
7
|
+
*/
|
|
8
|
+
export async function analyzeUnusedExports(files, projectPath) {
|
|
9
|
+
const issues = [];
|
|
10
|
+
// Build complete export/import graph
|
|
11
|
+
const graph = buildExportGraph(files, projectPath);
|
|
12
|
+
// Find exports that are never imported
|
|
13
|
+
const unusedExports = findUnusedExports(graph, files, projectPath);
|
|
14
|
+
for (const { file, exportName, line } of unusedExports) {
|
|
15
|
+
const relPath = relative(projectPath, file);
|
|
16
|
+
// Skip if it's a default export from an entry point
|
|
17
|
+
if (isEntryPoint(file, projectPath)) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
issues.push({
|
|
21
|
+
type: "unused-export",
|
|
22
|
+
severity: "low",
|
|
23
|
+
file: relPath,
|
|
24
|
+
line,
|
|
25
|
+
pattern: `export ${exportName}`,
|
|
26
|
+
description: `'${exportName}' is exported but never imported in the analyzed codebase.`,
|
|
27
|
+
estimatedImpact: 500,
|
|
28
|
+
suggestion: {
|
|
29
|
+
title: "Remove unused export",
|
|
30
|
+
description: `If '${exportName}' is not used externally, consider removing it or marking it as internal.`,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return issues;
|
|
35
|
+
}
|
|
36
|
+
function buildExportGraph(files, projectPath) {
|
|
37
|
+
const exports = new Map();
|
|
38
|
+
const imports = new Map();
|
|
39
|
+
for (const file of files) {
|
|
40
|
+
try {
|
|
41
|
+
const content = readFileSync(file, "utf-8");
|
|
42
|
+
const fileExports = new Set();
|
|
43
|
+
const fileImports = new Map();
|
|
44
|
+
const ast = acorn.parse(content, {
|
|
45
|
+
ecmaVersion: "latest",
|
|
46
|
+
sourceType: "module",
|
|
47
|
+
locations: true,
|
|
48
|
+
});
|
|
49
|
+
walk.simple(ast, {
|
|
50
|
+
ExportNamedDeclaration(node) {
|
|
51
|
+
// export { a, b }
|
|
52
|
+
if (node.specifiers) {
|
|
53
|
+
for (const spec of node.specifiers) {
|
|
54
|
+
const exportedName = spec.exported?.name || spec.local?.name;
|
|
55
|
+
if (exportedName) {
|
|
56
|
+
fileExports.add(exportedName);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// export const/let/var/function/class
|
|
61
|
+
if (node.declaration) {
|
|
62
|
+
if (node.declaration.declarations) {
|
|
63
|
+
for (const decl of node.declaration.declarations) {
|
|
64
|
+
if (decl.id?.name) {
|
|
65
|
+
fileExports.add(decl.id.name);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else if (node.declaration.id?.name) {
|
|
70
|
+
fileExports.add(node.declaration.id.name);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
ExportDefaultDeclaration() {
|
|
75
|
+
fileExports.add("default");
|
|
76
|
+
},
|
|
77
|
+
ExportAllDeclaration(node) {
|
|
78
|
+
// export * from "..."
|
|
79
|
+
if (node.source?.value) {
|
|
80
|
+
fileExports.add(`* from ${node.source.value}`);
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
ImportDeclaration(node) {
|
|
84
|
+
if (!node.source?.value)
|
|
85
|
+
return;
|
|
86
|
+
const sourcePath = node.source.value;
|
|
87
|
+
for (const spec of node.specifiers || []) {
|
|
88
|
+
if (spec.type === "ImportSpecifier") {
|
|
89
|
+
const importedName = spec.imported?.name;
|
|
90
|
+
if (importedName) {
|
|
91
|
+
fileImports.set(importedName, resolveImportPath(file, sourcePath));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else if (spec.type === "ImportDefaultSpecifier") {
|
|
95
|
+
fileImports.set("default", resolveImportPath(file, sourcePath));
|
|
96
|
+
}
|
|
97
|
+
else if (spec.type === "ImportNamespaceSpecifier") {
|
|
98
|
+
fileImports.set("*", resolveImportPath(file, sourcePath));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
exports.set(file, fileExports);
|
|
104
|
+
imports.set(file, fileImports);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
// Skip files that can't be parsed
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return { exports, imports };
|
|
111
|
+
}
|
|
112
|
+
function findUnusedExports(graph, files, projectPath) {
|
|
113
|
+
const unusedExports = [];
|
|
114
|
+
// Collect all imported names across the codebase
|
|
115
|
+
const allImports = new Map(); // source file -> imported names
|
|
116
|
+
for (const [importingFile, fileImports] of graph.imports) {
|
|
117
|
+
for (const [importedName, sourceFile] of fileImports) {
|
|
118
|
+
if (!allImports.has(sourceFile)) {
|
|
119
|
+
allImports.set(sourceFile, new Set());
|
|
120
|
+
}
|
|
121
|
+
allImports.get(sourceFile).add(importedName);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Check each export against imports
|
|
125
|
+
for (const [file, fileExports] of graph.exports) {
|
|
126
|
+
const usedInFile = allImports.get(file) || new Set();
|
|
127
|
+
for (const exportName of fileExports) {
|
|
128
|
+
// Skip wildcard re-exports
|
|
129
|
+
if (exportName.startsWith("*"))
|
|
130
|
+
continue;
|
|
131
|
+
// Check if this export is used
|
|
132
|
+
const isUsed = usedInFile.has(exportName) ||
|
|
133
|
+
usedInFile.has("*") || // namespace import uses all
|
|
134
|
+
(exportName === "default" && usedInFile.has("default"));
|
|
135
|
+
if (!isUsed) {
|
|
136
|
+
unusedExports.push({
|
|
137
|
+
file,
|
|
138
|
+
exportName,
|
|
139
|
+
line: getExportLine(file, exportName),
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return unusedExports;
|
|
145
|
+
}
|
|
146
|
+
function resolveImportPath(fromFile, importPath) {
|
|
147
|
+
// Handle relative imports
|
|
148
|
+
if (importPath.startsWith(".")) {
|
|
149
|
+
const dir = dirname(fromFile);
|
|
150
|
+
let resolved = resolve(dir, importPath);
|
|
151
|
+
// Add common extensions if needed
|
|
152
|
+
const extensions = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".mts", ""];
|
|
153
|
+
for (const ext of extensions) {
|
|
154
|
+
if (resolved.endsWith(ext)) {
|
|
155
|
+
return resolved;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// Try adding extensions
|
|
159
|
+
return resolved;
|
|
160
|
+
}
|
|
161
|
+
// For node_modules, return as-is
|
|
162
|
+
return importPath;
|
|
163
|
+
}
|
|
164
|
+
function isEntryPoint(file, projectPath) {
|
|
165
|
+
const relPath = relative(projectPath, file).toLowerCase();
|
|
166
|
+
// Common entry point patterns
|
|
167
|
+
const entryPatterns = [
|
|
168
|
+
/^src\/index\./,
|
|
169
|
+
/^src\/main\./,
|
|
170
|
+
/^src\/app\./,
|
|
171
|
+
/^index\./,
|
|
172
|
+
/^main\./,
|
|
173
|
+
];
|
|
174
|
+
return entryPatterns.some((pattern) => pattern.test(relPath));
|
|
175
|
+
}
|
|
176
|
+
function getExportLine(file, exportName) {
|
|
177
|
+
try {
|
|
178
|
+
const content = readFileSync(file, "utf-8");
|
|
179
|
+
const lines = content.split("\n");
|
|
180
|
+
for (let i = 0; i < lines.length; i++) {
|
|
181
|
+
const line = lines[i];
|
|
182
|
+
if (line.includes(`export`) && line.includes(exportName)) {
|
|
183
|
+
return i + 1;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
// Ignore
|
|
189
|
+
}
|
|
190
|
+
return 0;
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=exports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exports.js","sourceRoot":"","sources":["../../src/analyzers/exports.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { TreeShakingIssue } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Analyze files to detect CommonJS vs ESM module patterns
|
|
4
|
+
*/
|
|
5
|
+
export declare function analyzeModuleTypes(files: string[], projectPath: string): Promise<TreeShakingIssue[]>;
|
|
6
|
+
//# sourceMappingURL=module-type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module-type.d.ts","sourceRoot":"","sources":["../../src/analyzers/module-type.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAoB1D;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EAAE,EACf,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAc7B"}
|