DEV Community

Cover image for eslint-plugin-import vs eslint-plugin-import-next: Up to 100x Faster
Ofri Peretz
Ofri Peretz

Posted on • Edited on

eslint-plugin-import vs eslint-plugin-import-next: Up to 100x Faster

Up to 100x faster on circular dependency detection. Reproducible benchmarks. Full methodology.

πŸ”„ Drop-in replacement β€” 100% compatible with all eslint-plugin-import rules, but faster, LLM-optimized error messages, and fewer false positives/negatives.

TL;DR

Benchmark 1K Files 5K Files 10K Files
Core Rules (9) 1.6x 3.3x 5.2x
Recommended Preset 1.4x 3.0x 5.5x
no-cycle Only 25.7x 54.9x ~100x*

*10K projection based on O(n²) scaling pattern observed at 1K→5K. We stopped at 5K because eslint-plugin-import would take 10+ minutes.


Why eslint-plugin-import is Slow

The original eslint-plugin-import uses an O(nΒ²) module resolution algorithm:

  1. For each file, parse all imports
  2. For each import, resolve the full module path
  3. For no-cycle, traverse the entire dependency graph for every file

This creates quadratic complexity. On 5,000 files with interconnected imports, the no-cycle rule alone takes 148 seconds.

How eslint-plugin-import-next Fixes This

We rewrote the core algorithms:

  1. Cached module resolution β€” resolve each path once, cache permanently
  2. Incremental graph building β€” build the dependency graph incrementally, not per-file
  3. Cycle detection with Tarjan's algorithm β€” O(n) instead of O(nΒ²)

Result: 2.71 seconds for the same 5,000 files.


Benchmark 1: Core Rules (9 rules)

Both plugins configured with identical rules:

  • no-unresolved, named, namespace, default, export
  • no-named-as-default, no-named-as-default-member, no-duplicates, order
Files eslint-plugin-import eslint-plugin-import-next Speedup
1,000 2.80s 1.78s 1.6x
5,000 19.04s 5.76s 3.3x
10,000 58.67s 11.26s 5.2x

Takeaway: Even with basic rules, the performance gap grows with codebase size.


Benchmark 2: Recommended Preset

Using the full recommended configuration from each plugin.

Files eslint-plugin-import eslint-plugin-import-next Speedup
1,000 2.42s 1.78s 1.4x
5,000 18.43s 6.07s 3.0x
10,000 57.74s 10.57s 5.5x

Takeaway: Recommended presets show similar scaling β€” 5.5x faster at 10K files.


Benchmark 3: no-cycle Rule Only

This is where the difference is massive. The no-cycle rule detects circular dependencies.

Files eslint-plugin-import eslint-plugin-import-next Speedup
1,000 27.03s 1.05s 25.7x
5,000 148.59s 2.71s 54.9x
10,000 ~600s (projected)* ~5s (projected) ~100x

*10K Projection Note: Based on the O(n²) scaling observed from 1K→5K (27s→148s = 5.5x increase for 5x files), we project eslint-plugin-import would take ~10 minutes at 10K files. We didn't run this because waiting 10+ minutes per iteration is impractical. eslint-plugin-import-next scales linearly (O(n)), so ~5s is expected.

Takeaway: If you use no-cycle (and you should), the speedup is 25-100x depending on codebase size.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ no-cycle Rule: 5,000 files                                     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ eslint-plugin-import:      148.59s β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ”‚
β”‚ eslint-plugin-import-next:   2.71s β–ˆ                           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Enter fullscreen mode Exit fullscreen mode

Why no-cycle is Critical

Circular dependencies cause:

  • Build failures with tree-shaking
  • Runtime bugs with undefined imports
  • Memory leaks in bundlers
  • Test flakiness from initialization order

Most teams disable no-cycle because it's too slow. With eslint-plugin-import-next, you can finally enable it.


Methodology

Apple-to-apple comparison β€” full source code

Spec Details
Codebase sizes 1,000 / 5,000 / 10,000 JavaScript files
Iterations 3-5 runs per size, per plugin
Fixtures Realistic JS files with named/default imports, barrel files, cross-file dependencies
Environment Node v20.19.5, Apple Silicon M1 (arm64), ESLint v9.17.0
Cache Cleared between each run

Run It Yourself

git clone https://github.com/ofri-peretz/eslint-benchmark-suite.git
cd eslint-benchmark-suite
npm install
npm run generate:import
npm run benchmark:import
npm run benchmark:import-recommended
npm run benchmark:import-no-cycle
Enter fullscreen mode Exit fullscreen mode

Migration Takes 2 Minutes

# Remove old plugin
npm uninstall eslint-plugin-import

# Install new plugin
npm install --save-dev eslint-plugin-import-next
Enter fullscreen mode Exit fullscreen mode
// eslint.config.js
import importNext from 'eslint-plugin-import-next';
export default [importNext.configs.recommended];
Enter fullscreen mode Exit fullscreen mode

Resources

πŸ“¦ npm: eslint-plugin-import-next
πŸ“Š Benchmark Suite
πŸ“– Full Rule List

⭐ Star on GitHub


πŸš€ Are you still waiting 45+ seconds for ESLint? Try import-next and share your results!

For more updates, follow me on:

GitHub | LinkedIn | Dev.to


Copyright (c) 2025 Ofri Peretz. All rights reserved.

Top comments (0)