@fe-fast/unused-css-pruner
Version:
A powerful CSS pruning tool that removes unused styles with support for dynamic class names, CSS-in-JS, and component-level analysis
520 lines (398 loc) • 12 kB
Markdown
# CSS Pruner 🌿
A powerful and intelligent CSS cleanup tool that identifies and removes unused CSS selectors from your projects. Built with TypeScript and designed to integrate seamlessly with modern development workflows.
## Features ✨
- 🔍 **Smart Analysis**: Detects unused CSS selectors across your entire codebase
- 🚀 **Framework Support**: Works with Vue, React, Angular, and vanilla HTML/JS
- 🎯 **Dynamic Class Detection**: Handles Tailwind CSS, CSS-in-JS, and template literals
- 📊 **Multiple Report Formats**: Console, JSON, and beautiful HTML reports
- ⚙️ **Highly Configurable**: Extensive configuration options with smart defaults
- 🛡️ **Safe by Default**: Dry-run mode and whitelist support
- 📦 **Zero Dependencies**: Lightweight with minimal external dependencies
- 🔧 **CLI & Programmatic API**: Use as a command-line tool or integrate into your build process
## Installation 📦
```bash
# Using npm
npm install -g @fe-fast/unused-css-pruner
# Using yarn
yarn global add @fe-fast/unused-css-pruner
# Using pnpm
pnpm add -g @fe-fast/unused-css-pruner
# For project-specific usage
npm install --save-dev @fe-fast/unused-css-pruner
```
## Quick Start 🚀
### Command Line Usage
```bash
# Analyze CSS usage
css-pruner analyze --css "src/**/*.css" --source "src"
# Clean CSS files (dry run)
css-pruner clean --css "src/**/*.css" --source "src" --dry-run
# Generate HTML report
css-pruner analyze --css "src/**/*.css" --source "src" --format html --output report.html
# Initialize configuration file
css-pruner init
```
### Programmatic Usage
```typescript
import { analyzeCSSUsage, cleanCSS } from '@fe-fast/unused-css-pruner';
// Analyze CSS usage
const result = await analyzeCSSUsage({
cssFiles: ['src/**/*.css'],
sourceDirectories: ['src'],
config: {
reportFormat: 'json',
verbose: true
}
});
console.log(`Found ${result.stats.unusedSelectors} unused selectors`);
// Clean CSS files
const { result: cleanResult, cleanedFiles } = await cleanCSS({
cssFiles: ['src/**/*.css'],
sourceDirectories: ['src'],
outputDir: 'dist',
dryRun: false
});
```
## Configuration 🔧
Create a `css-pruner.config.js` file in your project root:
```javascript
module.exports = {
// CSS files to analyze (glob patterns supported)
cssFiles: ['src/**/*.css', '!src/**/*.min.css'],
// Source directories to scan for class usage
sourceDirectories: ['src', 'components'],
// Patterns to ignore
ignorePatterns: [
'node_modules/**',
'dist/**',
'build/**'
],
// Selectors to always keep (whitelist)
whitelist: [
'sr-only',
'visually-hidden',
/^wp-/, // WordPress classes
/^js-/, // JavaScript hooks
/^is-/, // State classes
/^has-/ // State classes
],
// File extensions to scan
fileExtensions: ['.vue', '.jsx', '.tsx', '.js', '.ts', '.html'],
// Report format: 'console', 'json', 'html'
reportFormat: 'console',
// Verbose logging
verbose: false,
// Dry run mode
dryRun: false
};
```
## CLI Commands 💻
### `analyze`
Analyze CSS files and generate usage reports.
```bash
css-pruner analyze [options]
Options:
--css <patterns> CSS files to analyze (glob patterns)
--source <dirs> Source directories to scan
--config <file> Configuration file path
--format <format> Report format (console|json|html)
--output <file> Output file for reports
--verbose Enable verbose logging
```
### `clean`
Remove unused CSS selectors from files.
```bash
css-pruner clean [options]
Options:
--css <patterns> CSS files to clean
--source <dirs> Source directories to scan
--output <dir> Output directory for cleaned files
--dry-run Preview changes without modifying files
--config <file> Configuration file path
--verbose Enable verbose logging
```
### `init`
Create a sample configuration file.
```bash
css-pruner init [filename]
```
## Framework Integration 🔗
### Webpack Plugin
```javascript
const CSSPrunerPlugin = require('@fe-fast/unused-css-pruner/webpack');
module.exports = {
plugins: [
new CSSPrunerPlugin({
cssFiles: ['dist/**/*.css'],
sourceDirectories: ['src'],
outputDir: 'dist'
})
]
};
```
### Vite Plugin
```javascript
import { cssPruner } from '@fe-fast/unused-css-pruner/vite';
export default {
plugins: [
cssPruner({
cssFiles: ['dist/**/*.css'],
sourceDirectories: ['src']
})
]
};
```
### Rollup Plugin
```javascript
import { cssPruner } from '@fe-fast/unused-css-pruner/rollup';
export default {
plugins: [
cssPruner({
cssFiles: ['dist/**/*.css'],
sourceDirectories: ['src']
})
]
};
```
## Advanced Features 🎯
### Dynamic Class Detection
CSS Pruner intelligently detects dynamically generated classes:
```javascript
// Tailwind CSS JIT
const className = `bg-${color}-500`;
// CSS-in-JS
const styles = css`
.${dynamicClass} {
color: red;
}
`;
// Template literals
const buttonClass = `btn btn-${variant} ${size}`;
```
### Whitelist Patterns
Protect important selectors from removal:
```javascript
module.exports = {
whitelist: [
// Exact matches
'sr-only',
'visually-hidden',
// Regular expressions
/^wp-/, // WordPress classes
/^woocommerce-/, // WooCommerce classes
/^elementor-/, // Elementor classes
/^js-/, // JavaScript hooks
/^is-/, // State classes
/^has-/, // State classes
// Responsive prefixes (Tailwind)
/^sm:/,
/^md:/,
/^lg:/,
/^xl:/,
/^2xl:/
]
};
```
### Custom Dynamic Patterns
Add your own patterns for dynamic class detection:
```javascript
module.exports = {
dynamicClassPatterns: [
// Your custom framework patterns
/\bmyframework-\w+/,
/\bcomponent-[a-z0-9-]+/,
// Template engine patterns
/\{\{[^}]+\}\}/,
/\{%[^%]+%\}/
]
};
```
## Examples 🚀
The `examples/` directory contains three comprehensive demo projects that showcase CSS Pruner's capabilities with different build systems and frameworks. Each example includes intentionally redundant CSS classes to demonstrate the tool's effectiveness.
### Available Examples
#### 1. Webpack + React Example
**Location**: `examples/webpack-react-example/`
**Features**:
- React 18 with functional components and hooks
- Webpack 5 with CSS extraction
- Interactive counter application with reusable components
- Extensive unused CSS classes for testing
**Quick Start**:
```bash
cd examples/webpack-react-example
npm install
npm run build
npm run css-prune
```
#### 2. Vite + Vue Example
**Location**: `examples/vite-vue-example/`
**Features**:
- Vue 3 with Composition API
- Vite for fast development and building
- Interactive todo list and counter functionality
- Vue-specific CSS class patterns
**Quick Start**:
```bash
cd examples/vite-vue-example
npm install
npm run build
npm run css-prune
```
#### 3. Rollup + Vue Example
**Location**: `examples/rollup-vue-example/`
**Features**:
- Vue 3 with advanced component architecture
- Rollup for optimized bundling
- Interactive dashboard with task management
- Comprehensive CSS utility classes
**Quick Start**:
```bash
cd examples/rollup-vue-example
npm install
npm run build
npm run analyze-css
```
### What Each Example Demonstrates
**Common CSS Patterns Tested**:
- Layout & Grid Systems (Bootstrap-style classes)
- Component Variants (buttons, cards, forms)
- Utility Classes (spacing, typography, colors)
- Animations & Effects
- Framework-specific patterns
**Expected Results**:
Each example should detect **60-80% unused CSS classes**, demonstrating:
- High detection accuracy
- Framework compatibility
- Build tool integration
- Comprehensive report generation
**Typical Output**:
```
📊 CSS Analysis Results:
📁 CSS Files Analyzed: 1
📄 Total CSS Rules: ~200-300
✅ Used CSS Classes: ~60-80
❌ Unused CSS Classes: ~120-200
📉 Potential Size Reduction: 60-75%
```
### Running Examples
For any example:
1. **Navigate to example directory**:
```bash
cd examples/[example-name]
```
2. **Install dependencies**:
```bash
npm install
```
3. **Build the project**:
```bash
npm run build
```
4. **Run CSS analysis**:
```bash
npm run css-prune # or npm run analyze-css
```
5. **View results**:
- Check console output for summary
- Open `css-analysis/report.html` for detailed view
- Review `css-analysis/report.json` for programmatic access
6. **Preview application** (optional):
```bash
npm run preview # or npm run dev
```
### Configuration Files
Each example includes:
- **`css-pruner.config.js`**: CSS Pruner configuration
- **Build config**: Framework-specific build configuration
- **`package.json`**: Dependencies and npm scripts
- **`README.md`**: Example-specific documentation
For detailed information about each example, see the README files in their respective directories.
## Report Formats 📊
### Console Report
Colorful, detailed console output with statistics and recommendations.
### JSON Report
Machine-readable format perfect for CI/CD integration:
```json
{
"summary": {
"totalSelectors": 1250,
"usedSelectors": 892,
"unusedSelectors": 358,
"potentialSavings": 45600,
"usageRate": 71.4
},
"unusedSelectors": [...],
"fileBreakdown": [...],
"recommendations": [...]
}
```
### HTML Report
Beautiful, interactive HTML report with charts and detailed analysis.
## Best Practices 💡
1. **Start with Analysis**: Always run analysis before cleaning
2. **Use Dry Run**: Test with `--dry-run` flag first
3. **Configure Whitelist**: Add framework-specific classes to whitelist
4. **Version Control**: Commit before running cleanup
5. **Test Thoroughly**: Test your application after cleanup
6. **Incremental Cleanup**: Clean one component/page at a time for large projects
## CI/CD Integration 🔄
### GitHub Actions
```yaml
name: CSS Analysis
on: [push, pull_request]
jobs:
css-analysis:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '18'
- run: npm install
- run: npx css-pruner analyze --css "src/**/*.css" --source "src" --format json --output css-report.json
- uses: actions/upload-artifact@v2
with:
name: css-analysis-report
path: css-report.json
```
### Pre-commit Hook
```json
{
"husky": {
"hooks": {
"pre-commit": "css-pruner analyze --css 'src/**/*.css' --source 'src' && lint-staged"
}
}
}
```
## Troubleshooting 🔧
### Common Issues
**Q: Some used classes are marked as unused**
A: Add them to the whitelist or check if they're dynamically generated.
**Q: Analysis is slow on large projects**
A: Use more specific glob patterns and exclude unnecessary directories.
**Q: False positives with framework classes**
A: Configure framework-specific whitelist patterns.
**Q: Dynamic classes not detected**
A: Add custom patterns to `dynamicClassPatterns` configuration.
### Debug Mode
```bash
css-pruner analyze --verbose --css "src/**/*.css" --source "src"
```
## Contributing 🤝
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
## License 📄
MIT License - see the [LICENSE](LICENSE) file for details.
## Changelog 📝
See [CHANGELOG.md](CHANGELOG.md) for a list of changes.
## Support 💬
- 📖 [Documentation]
- 🐛 [Issue Tracker](https://github.com/william-xue/css-pruner/issues)
- 💬 [Discussions](https://github.com/william-xue/css-pruner/discussions)
- 📧 [Email Support]