Get Started
- CodeAnt AI
- Control Center
- Pull Request Review
- IDE
- Compliance
- Anti-Patterns
- Code Governance
- Infrastructure Security Database
- Application Security Database
Import
Enforce or ban the use of inline type-only markers for named imports.
// Bad code: Using a top-level type-only import
import type { SomeType } from './types';
- Ensures consistency in the usage of type-only import specifiers across the project, which can make the codebase more readable and easier to understand for new developers or contributors.
- Helps maintain a uniform code style rule for type imports, reducing the chances of syntax variations that could lead to merge conflicts or style disagreements within a team.
- Can potentially simplify the process of refactoring or updating import statements, as it enforces a specific pattern that tools and developers can reliably predict and work with.
- Aids in the avoidance of potential build or compiler toolchain issues that may arise from inconsistent usage of types and value imports, by ensuring that all type imports follow a singular, consistent pattern throughout the application.
Ensure a default export is present, given a default import.
// file1.js
export const myFunc = () => {
console.log("This is a function from file1.");
};
// file2.js
import myFunc from './file1';
myFunc();
-
Ensures consistency in how modules are imported and exported across a project by enforcing a rule that if a module is imported with a default import syntax, there must be a corresponding default export in the imported module. This helps in maintaining a uniform coding standard and reduces confusion.
-
Improves code readability and maintainability by making the imports and exports more predictable. When developers know that a default import must have a corresponding default export, it’s easier to trace module dependencies and understand the structure of the codebase.
-
Assists in preventing runtime errors that occur when a default import is expected, but the module does not provide a default export. These errors can be difficult to debug, especially in a large codebase. Applying this rule helps to catch such issues during development before they cause problems in production.
-
Encourages the use of default exports in modules where a single entity is being exported, which can lead to cleaner and more concise code. By enforcing a default export for default imports, it pushes towards a module structure where the main functionality is easily identifiable and accessible through a straightforward import syntax.
Enforce a leading comment with the webpackChunkName for dynamic imports.
function loadComponent() {
return import('./MyComponent');
}
- The rule ensures that dynamic imports in codebases using Webpack for module bundling explicitly specify a
webpackChunkName
. This helps in generating more predictable and identifiable chunk filenames during the build process, which is crucial for debugging and optimizing the load of scripts. - By requiring a leading comment with the
webpackChunkName
for dynamic imports, the rule fosters better code documentation and readability. It makes it clear to developers working on the project which chunks correspond to which dynamic imports, facilitating easier maintenance and understanding of the codebase. - This rule aids in performance optimization practices by encouraging the use of named chunks. Developers can leverage these names to implement more refined preloading or prefetching strategies in their applications, directly impacting the user experience by reducing load times and improving interactivity.
- Enforcing the inclusion of a
webpackChunkName
through this rule can also assist in more effective cache management on the client-side. By having named chunks, it becomes easier to invalidate the cache for specific modules when they are updated, rather than forcing a download of the entire bundle again, thus optimizing bandwidth usage and update deployment.
Forbid any invalid exports, i.e. re-export of the same name.
// file: mathUtils.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
// file: index.js
export { add } from './mathUtils.js';
export { add as addNumbers } from './mathUtils.js'; // This re-export of `add` violates the rule.
- The rule specifically prevents the re-export of the same named export, which can lead to confusion and errors in module composition. By ensuring each exported name is unique, it helps maintain clear module boundaries and relationships.
- It contributes to code maintainability and readability by avoiding unnecessary complexity in export statements. Developers can quickly understand the module’s exports without parsing through duplicate names or aliases that point to the same export.
- The rule assists in avoiding runtime errors or hard-to-debug issues caused by shadowing or unintentionally overriding exports when multiple files are involved. This is especially helpful in large projects where the same name might be exported from different modules.
- It aligns with best practices for modular JavaScript development, encouraging developers to structure their code in a way that promotes clarity in export relationships. This ensures that exports are straightforward and predictable, which is beneficial for both development and refactoring stages.
Ensure all exports appear after other statements.
export const myExportedFunc = () => {
console.log('This function is exported');
};
const helperFunction = () => {
console.log('This is a helper function');
};
helperFunction();
- Ensures consistency in code structure by enforcing all export statements to be placed at the bottom of the file, which can help in identifying exported members quickly without scanning the entire file.
- Facilitates easier readability and maintainability of code, as developers can clearly distinguish between module’s internal logic and its public interface.
- Prevents accidentally exporting something in the middle of a file, which could lead to confusion about the module’s interface and its internal workings among developers.
- Supports better organization of code, by creating a convention that separates the implementation details from the module’s exports, leading to cleaner and more structured coding practices.
Ensure consistent use of file extension within the import path.
// Assuming we have a local module named `example`.
import Example from './example';
- Ensures consistency in the codebase by enforcing a uniform approach to the inclusion or exclusion of file extensions in import paths, which can help in reducing confusion among developers and maintain consistency across different environments or setups.
- Helps in avoiding potential resolution issues that may occur when the environment or build tools expect a certain format for module resolution. For instance, some bundlers or node environments might need the explicit extension to resolve the file correctly.
- Improves readability and clarity for developers, especially in a project with files having the same name but different extensions. Specifying the extension can immediately make it clear which module is being imported without the need to open the file or check its type.
- Aids in the configuration of tooling and build processes by making explicit the type of modules being imported, thus potentially optimizing bundling or transpilation steps by providing clear cues about the nature of each import (e.g., JS, TS, JSON, etc.).
Ensure all imports appear before other statements.
const greeting = "Hello, world!";
import { sayHello } from './hello';
console.log(sayHello(greeting));
-
This ESLint rule enforces a consistent structure in module files by ensuring that all import statements are placed at the beginning of the file, before any other statements. This makes the file easier to read and understand because all dependencies are declared upfront.
-
By grouping all import statements at the top, it becomes easier to identify which modules or files the current file depends on, enhancing the maintainability of the code. Developers can quickly see dependencies without having to search through the entire file.
-
The rule helps prevent errors that may occur due to hoisting. JavaScript hoists declarations but not initializations. If a file contains imports scattered throughout, it might lead to situations where a module is used before it’s imported due to the way JavaScript hoists declarations.
-
This rule supports automatic fixing, meaning it can automatically reorder the code to place imports at the top of the file. This feature can save developers time during the development process by automatically resolving formatting issues, ensuring consistent code structure without manual intervention.
Prefer named exports to be grouped together in a single export declaration
// Separate named exports
export const pi = 3.14159;
export function calculateArea(radius) {
return pi * radius * radius;
}
export function calculateCircumference(radius) {
return 2 * pi * radius;
}
- Encourages a cleaner, more organized codebase by consolidating all named exports into a single export statement, reducing the amount of export statements scattered throughout the file. This makes it easier to see at a glance everything that the module is exporting.
- Can improve maintainability by grouping all exports together, which simplifies refactoring when the set of exported entities changes. For instance, adding, removing, or renaming exports can be done in one location rather than multiple places across the file.
- This rule aids in promoting consistency across a codebase, especially in larger projects where multiple developers are working on different modules. A consistent exporting style can make it easier for team members to understand and navigate the project structure.
- May potentially lead to minor performance improvements in the JavaScript engine’s parsing phase by reducing the number of export statements. Grouping exports together could slightly decrease the time it takes for the engine to parse the module, though this impact is likely negligible in most cases.
Replaced by import/first
.
// Example of code that would be flagged by `import/imports-first`
const greeting = 'Hello, world!';
import { moduleA } from './moduleA';
import { moduleB } from './moduleB';
-
The rule helps maintain a consistent order of imports at the beginning of the file, making it easier to read and understand the dependencies of the module. This can be particularly beneficial in modules with a large number of imports or complex dependencies.
-
It enforces a separation of import statements from other module logic, reducing the likelihood of import-related errors and improving module clarity. For example, it flags cases where import statements are interspersed with other statements, which could lead to less predictable execution order dependencies.
-
The rule supports the option ‘absolute-first’ which ensures that absolute imports are placed before relative imports. This distinction can help in quickly identifying external dependencies versus internal module references, contributing to better module architecture understanding.
-
By providing autofix functionality, the rule assists in automatically reordering the imports according to the specified guidelines, saving developer time and ensuring code consistency across a project without manual intervention. This can be particularly useful in large projects or teams, ensuring the codebase adheres to the same standards effortlessly.
Enforce the maximum number of dependencies a module can have.
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import Helper from './Helper';
import Util from './Util';
import Service from './Service';
class MyComponent extends React.Component {
// Component implementation
}
// More code related to MyComponent, like PropTypes, Redux connection, etc.
- Encourages modular and cohesive design by limiting the number of dependencies a module can have, which can help in identifying overly complex modules that may need refactoring.
- Promotes better project maintenance and readability by avoiding clutter with too many imports at the top of a file. A module with fewer dependencies is easier to understand, debug, and test.
- Can lead to better performance practices by forcing developers to consider the necessity of each dependency. This might reduce the final bundle size in front-end projects by preventing unnecessary imports.
- Facilitates a cleaner codebase where the use of aggregated modules is encouraged over individual imports for closely related functionalities, leading to a more organized and potentially more efficient code structure.
Ensure named imports correspond to a named export in the remote file.
// Assuming the file 'someModule.js' does not export 'missingName'
import { missingName } from './someModule';
console.log(missingName);
- This ESLint rule ensures that named imports in a JavaScript file correspond directly to named exports in the imported module, promoting consistency and reducing the risk of runtime errors due to misnamed imports, which can be especially beneficial in large projects where tracking exports and imports manually becomes impractical.
- It automatically detects and reports missing exports for requested imports by analyzing the relationship between import specifiers and the actual named exports from the source files, thus helping developers to identify and fix incorrect import statements promptly.
- The rule encompasses checks for both ES2015 module syntax (
import { namedExport } from 'module'
) and CommonJS require syntax with destructuring (const { namedExport } = require('module')
), making it versatile and applicable to a wide range of JavaScript projects with different module systems. - By providing detailed error messages, including the path through which a missing export was attempted to be accessed (for deep member imports), it aids developers in pinpointing the source of the error quickly, enhancing the debugging process and improving developer productivity.
Ensure imported namespaces contain dereferenced properties as they are dereferenced.
// Example module: stuff.js
export const items = {};
// In another file where the violation occurs:
import * as Stuff from './stuff';
// Attempting to directly modify a property of the imported namespace
Stuff.items.newItem = 'This is a new item';
- This rule prevents the direct manipulation of imported namespaces, which ensures that the integrity and immutability of imported modules are maintained. Direct modifications to namespaces, as highlighted in the ‘bad’ example, can lead to unpredictable side effects and bugs, especially in large codebases.
- It encourages the use of a module’s publicly exposed methods for interacting with its exported entities. This aligns with the principle of encapsulation in modular programming, allowing module authors to control how their modules are consumed and interacted with, as shown in the ‘fix’ example.
- The rule mitigates potential runtime errors that could arise from attempting to add or modify properties on an imported namespace object that is, under strict module systems, read-only. JavaScript modules are designed to be static and read-only, and this rule enforces this aspect at the linting level.
- By flagging computed property access on namespaces unless specifically allowed through rule options (
allowComputed
), it aids in maintaining static analyzability of the code. Static analysis tools can more easily reason about the code’s behavior when it adheres to more predictable, static access patterns. This makes the codebase easier to optimize, refactor, and debug.
Enforce a newline after import statements.
import { exampleFunction } from 'example-module';
const x = exampleFunction();
- This rule enforces a visual separation between import statements and subsequent code, which can improve the readability of the code by clearly distinguishing between dependency imports and the actual logic or definitions that follow. This makes it easier for developers to quickly understand the structure of the file at a glance.
- By requiring a newline after import statements, the rule can help maintain a consistent code style across the project. This consistency aids in reducing cognitive load when moving between files, as developers can expect a uniform format, thereby speeding up the process of understanding new codebases.
- The rule provides an automatic fix feature, which can insert the required newline(s) if they’re missing. This capability can save developers time during both development and code review processes by automatically resolving style issues related to newlines after imports, rather than requiring manual adjustments.
- It supports options for exact newline counts and consideration of comments, offering flexibility to accommodate different coding standards within teams or projects. This means that the rule can be finely tuned to match the specific stylistic preferences or requirements of a project, ensuring that the codebase adheres to its intended style guide without imposing a one-size-fits-all approach.
Forbid import of modules using absolute paths.
// Example of bad code
import someModule from '/absolute/path/to/someModule';
- Promotes code portability across different environments by ensuring all module imports use relative, rather than absolute paths, avoiding path-related errors when the project is moved or cloned into another directory structure.
- Enhances readability and maintainability of code by making the dependencies between modules clearer through relative path imports, thus making it easier for developers to navigate the project’s structure.
- Facilitates easier refactoring and reorganization of the project’s file structure, since relative paths adapt automatically as long as the relative positions of files remain unchanged, unlike absolute paths which would need manual updating.
- Prevents potential confusion and conflicts in larger projects by avoiding the use of absolute paths, which might accidentally overlap with node_modules or other system-wide available modules, ensuring that imports are explicitly relative to the project’s structure.
Forbid AMD require
and define
calls.
// Using AMD `require`
require(['dependency'], function (dependency) {
// Module code goes here
});
// Using AMD `define`
define(['dependency1', 'dependency2'], function (dependency1, dependency2) {
// Definition code goes here
});
- The rule ensures consistency in the codebase by enforcing the use of ES module syntax over AMD’s
require
anddefine
functions, which is important for projects that aim to maintain a modern JavaScript codebase. - It helps in the transition to ES modules, which are statically analyzable by JavaScript engines and tools, thereby potentially improving load times and optimizing dependency management.
- Preventing the use of AMD syntax aligns with the growing ecosystem of JavaScript tooling (like bundlers and linters) that are optimized for ES module syntax, ensuring better compatibility and fewer issues with tool integrations.
- By enforcing the use of ES module imports, the rule can help reduce the cognitive load for developers by standardizing on a single module system, making the code easier to read and maintain, especially for new developers who might be more familiar with ES modules than AMD.
Forbid anonymous values as default exports.
// Anonymous function exported directly
export default () => {
console.log('This is an anonymous function');
};
- Encourages code readability and maintainability by requiring all default exports to have a named identifier, making it easier to trace through code and debug.
- Enhances code consistency across a project by establishing a standard for exports, which can lead to improved collaboration and code quality among team members.
- Facilitates better code refactoring and analysis tools functionality, as named exports can be more easily located, refactored, or statically analyzed than anonymous default exports.
- Prevents ambiguity in the codebase about the origin and usage of defaulted exports, making it more straightforward to understand what is being exported and how it should be used or modified.
Forbid CommonJS require
calls and module.exports
or exports.*
.
const path = require('path');
-
Enforces the use of ES module syntax (e.g.,
import
andexport
) over CommonJS syntax (require
,module.exports
,exports.*
), ensuring consistency and readability within the codebase. This can be particularly important in projects that aim to be compliant with modern JavaScript standards or those transitioning from CommonJS to ES modules. -
Helps in the transition towards module bundlers like Webpack and transpilers like Babel that are optimized for ES modules. This can lead to potentially smaller bundle sizes and faster load times in web applications, as ES modules enable more efficient static analysis and tree shaking.
-
Prevents the mixed usage of CommonJS and ES module syntax within the same project, which can lead to confusion and errors. By forbidding CommonJS syntax, it ensures that developers adhere to one module system, reducing the cognitive load and making the code easier to maintain and debug.
-
Can improve cross-environment compatibility (Node.js vs. browser environments), as ES modules are natively supported in modern browsers. Using ES module syntax can therefore help in making code more portable and easier to run across different platforms without needing to rely on Node.js-specific features or polyfills.
Forbid a module from importing a module with a dependency path back to itself.
// a.js
import { bFunction } from './b.js';
export function aFunction() {
console.log('Function A');
bFunction();
}
- Prevents complexity and confusion in the codebase by disallowing modules to import each other in a circular manner, which can lead to harder-to-debug issues and unpredictable behavior during runtime. This ensures a more unidirectional flow of dependencies.
- Enhances code maintainability by enforcing clearer and more straightforward dependency paths. This rule helps in identifying and refactoring potential architectural flaws early, thereby reducing the technical debt associated with tangled dependencies.
- Improves the efficiency of the code execution, since cyclic dependencies can lead to excessive module re-evaluations, increased memory usage, and potential stack overflow errors during the module resolution phase.
- Supports configurable depth checking and exclusion patterns, making it flexible for a project to define its own thresholds for cyclic dependencies and to ignore certain cases like type imports or external modules. This adaptability allows teams to fine-tune the rule according to their project’s specific needs and avoid unnecessary noise in linting feedback.
Forbid default exports.
// badExample.js
function sum(a, b) {
return a + b;
}
export default sum;
- Enforces consistency in the export style across the codebase by advocating for named exports over default exports, making the code easier to maintain and refactor.
- Improves the readability and discoverability of modules within a project by explicitly naming what is being exported, aiding in documenting the codebase simply through its structure.
- Helps prevent conflicts and simplifies import statements by disallowing default exports which require import renaming to avoid naming clashes, thus supporting a clearer and more structured import process.
- Addresses the ambiguity in identifying the primary functionality of a module by discouraging the use of default exports, thereby encouraging developers to be explicit about each exported entity’s role and purpose.
Forbid imported names marked with @deprecated
documentation tag.
// myLibrary.js
/**
* @deprecated since version 1.2.0, use newFunction instead
*/
export function oldFunction() {
console.log("This function is deprecated.");
}
export function newFunction() {
console.log("This function is the recommended option.");
}
-
The rule specifically helps identify and report the usage of deprecated functions, classes, or variables within imported modules by scanning the
@deprecated
documentation tags. This ensures developers are alerted when they are relying on outdated parts of their dependencies that may be removed in future versions, thus encouraging the use of more current and supported features. -
By reporting deprecated imports at the time of writing or reviewing code, it enables early detection and remediation, reducing the potential for technical debt. As dependencies evolve and deprecate old functionalities, projects that do not adapt might find themselves with significant portions of their codebase relying on unsupported or insecure features. This rule, therefore, acts as a preventive measure against such scenarios.
-
It aids in maintaining code quality and standards within a project by ensuring that only current, non-deprecated APIs are used. This is particularly useful in large projects or teams where manually keeping track of deprecated functionalities across various dependencies can be a daunting task. Automation of this check reduces human error and oversight.
-
The rule not only checks for direct imports marked as deprecated but also extends its check to namespaces and deep imports. This thoroughness means that even if a deprecated function is accessed through a namespace import or multiple levels deep, it will still be detected and reported. Such a comprehensive approach ensures that even complex import structures don’t bypass the deprecation checks, maintaining the integrity and modernity of the codebase.
Forbid repeated import of the same module in multiple places.
import { someFunction } from './someModule';
import { anotherFunction } from './someModule';
someFunction();
anotherFunction();
- Enhances code readability and maintenance by ensuring that all imports from a single module are declared in one place, making it easier to see which functions or components are being used from that module.
- Reduces the risk of merge conflicts in collaborative projects as changes to imports from the same module are localized to a single area rather than scattered across multiple files or sections.
- May slightly improve build times or runtime performance in some systems by consolidating imports, which can help bundlers or optimizers process code more efficiently.
- Aids in identifying unused imports more straightforwardly, as it consolidates all imports from a module into a single line or block, making it easier to spot and remove unused or redundant imports during code cleanup or refactoring.
Forbid require()
calls with expressions.
// This code dynamically requires a module based on the `moduleName` var.
const moduleName = "express";
const package = require(moduleName);
- This rule helps in maintaining consistent, predictable imports throughout your project by ensuring that all
require()
calls are made with string literals, rather than expressions that evaluate at runtime. It makes the dependencies of a module easier to understand and analyze statically, which is essential for tooling and refactoring purposes. - By forbidding dynamic
require()
calls, the rule can significantly mitigate the risk of accidentally introducing security vulnerabilities, such as Remote Code Execution (RCE) vulnerabilities, through manipulatable input that might dynamically determine which modules are imported. - The restriction against dynamic imports encourages better coding practices by promoting the use of dependency injection or other patterns that enhance the modularity and testability of the code, instead of relying on conditional or runtime determination of dependencies.
- It improves the performance of the build process and the application. Static
require()
calls allow for more efficient bundling and dead code elimination by build tools like Webpack, which can statically analyze the dependency graph. Dynamic requires, on the other hand, may prevent these optimizations, leading to larger bundle sizes and slower application startup times.
Forbid empty named import blocks.
// Bad: Attempting to import named exports but the block is empty
import {} from 'someModule';
- Ensures that named imports from modules are actually specified, preventing the oversight of importing an empty set of bindings. This improves code clarity and avoids confusion about the module’s usage.
- Helps in identifying and removing dead code, as empty import blocks are often a result of refactoring or removal of used exports, thus keeping the codebase clean and efficient.
- Provides automatic fix suggestions that can either remove the unused import altogether or correct it to a side-effect import. This aids in faster code correction, aligning with the best practices of importing modules.
- Prevents a potential source of runtime errors or bundling issues in some JavaScript environments or build tools that may not handle empty import blocks gracefully, ensuring smoother development and deployment processes.
Forbid the use of extraneous packages.
// Assuming examplePackage is not listed in package.json dependencies or devDependencies
import { exampleFunction } from 'examplePackage';
function useExampleFunction() {
exampleFunction();
}
- This rule helps ensure that all imported packages are explicitly listed in the project’s
package.json
, which helps in avoiding runtime errors due to missing dependencies. When a package is imported but not defined inpackage.json
, it might work in a developer’s environment (due to the package being installed globally or as a part of another package) but fail in production or on another developer’s machine. - It aids in maintaining a clean codebase by preventing the use of packages that are not intended to be part of the project. This can be particularly useful in large projects where tracking dependencies manually becomes cumbersome, and there’s a risk of bloating the codebase with unnecessary imports.
- The rule allows for a detailed configuration that includes the allowance of devDependencies, optionalDependencies, peerDependencies, and even bundledDependencies for different files or directories. This flexibility ensures that in contexts where certain types of dependencies are acceptable (such as devDependencies in test files), the rule can be configured to allow those, reducing false positives and making the linter more useful.
- By verifying internal dependencies and type imports if specified in the options, this rule helps in ensuring that the project’s internal structure is also adhering to best practices regarding modularity and type safety. This can be particularly important in TypeScript projects or large JavaScript projects where internal dependencies can become as complex as external ones.
Forbid import statements with CommonJS module.exports.
// ES Module syntax
import express from 'express';
const app = express();
// Doing some express app setup
app.get('/', (req, res) => {
res.send('Hello World!');
});
// CommonJS syntax
module.exports = app;
- Enforces consistency in module definition by preventing the mix of CommonJS
module.exports
with ES module import syntax within the same file, which could lead to confusion or errors during the build or runtime phase due to differing module resolution mechanisms. - Helps in transitioning codebases towards a unified module syntax, either towards CommonJS or ES Modules, by highlighting instances where a contradictory syntax is used, thus supporting cleaner and more maintainable code.
- Aids in tooling optimization, as build tools and bundlers might have optimizations specific to either module system. Using a consistent module system allows these tools to apply optimizations more effectively, potentially resulting in faster build times and smaller bundles.
- Enhances code readability and team collaboration by establishing and enforcing a rule against mixing module systems. This can prevent potential misunderstandings or errors when different team members interact with or contribute to the codebase, especially in larger projects where consistency is key to maintainability.
Forbid importing the submodules of other modules.
// Bad practice: Importing a submodule directly
import { Button } from 'library/components/Button/index';
-
Encourages a modular architecture by restricting imports to top-level modules, which can lead to a more manageable and understandable codebase. This means developers are guided to use only the public interfaces provided by a module, discouraging tightly coupled component relationships and making refactoring easier.
-
Enhances code maintainability by preventing the use of internal paths in imports, which can be prone to breaking changes. When internal structures of a dependency change, it won’t directly break dependent codebases as long as the public API remains stable.
-
Improves package encapsulation by enforcing boundaries between different parts of the application or between different applications. This helps in clearly defining what is considered a public API and what is internal, thus making the distinction between what should and should not be relied upon clearer.
-
Assists in identifying and preventing potentially forbidden or bad practice patterns in codebase imports through customizable allow and forbid patterns. This allows teams to enforce specific architectural decisions or coding practices, tailor-made to the project’s or organization’s standards, improving code consistency across the codebase.
Forbid the use of mutable exports with var
or let
.
// Bad: Exporting a mutable binding
let exportedValue = "Initial value";
export { exportedValue };
-
The rule ‘import/no-mutable-exports’ specifically discourages the use of mutable exports, ensuring that exported values remain constant throughout the application. By enforcing the use of ‘const’ over ‘var’ or ‘let’ for exports, it helps maintain the immutability of exported values, reducing potential bugs related to value changes from other modules.
-
This rule directly contributes to a cleaner and more predictable codebase. Since ‘const’ makes the exported binding immutable, other developers or parts of the code can rely on the exported value to remain unchanged, leading to fewer side effects and easier debugging.
-
By promoting the use of immutability in exports, this rule potentially encourages better coding practices throughout the project. Developers become more mindful of the state and mutability of their data, fostering a more functional programming approach where data is transformed rather than modified.
-
It aids in application optimization. JavaScript engines often optimize code that deals with immutable data more effectively than mutable data. By exporting values as ‘const’, it gives a hint to the JavaScript engine that the value will not change, potentially leading to performance improvements in applications that heavily rely on module imports and exports.
Forbid use of exported name as property of default export.
// Assuming `getUserInfo` is a named export from './userActions'
import userActions from './userActions';
const userInfo = userActions.getUserInfo(userId);
-
Prevents Confusion in Codebase: This ESLint rule helps in maintaining clarity within the code by ensuring that named exports are not called as properties of the default export. By enforcing this rule, it reduces confusion among developers who might be unaware of the correct export forms, especially in large codebases where similar or identical naming can lead to misunderstandings about whether a given functionality is being imported as a part of the default export or as a named export.
-
Encourages Better Import Practices: By forbidding the use of exported names as properties of the default export, this rule pushes developers to use destructuring import syntax for named exports. This is not only syntactically clearer but also aligns with ES6 module standards, promoting better coding practices among developers.
-
Improves Static Analysis: Static analysis tools can more accurately identify and highlight errors when imports are explicitly stated. Since the rule enforces the use of named imports where applicable, it becomes easier for these tools to track down which modules are being used, how they’re being imported, and if there might be any namespace collisions or undefined references.
-
Facilitates Easier Refactoring and Tree Shaking: When named exports are used correctly, it makes the process of refactoring much smoother as it’s clearer which specific functionalities are being imported from modules. Additionally, this can improve the efficiency of tree shaking (removing unused code) in bundling tools since it’s more straightforward to determine which exports are actually being used in a project. This not only leads to better performance but also results in smaller bundle sizes.
Forbid use of exported name as identifier of default export.
// File: mathUtils.js
export const add = (a, b) => a + b;
export default { add };
// File: app.js
import mathUtils from './mathUtils';
console.log(mathUtils.add(2, 3)); // Works but it's confusing because `add` is both named export and a property of default export
-
Prevents ambiguity in module usage: The rule discourages using the same name for both a named export and a property of the default export, which can lead to confusion when the module is imported and used. This ensures clarity for developers on whether they’re using a property of the default export or a separate named export.
-
Enhances code readability and maintainability: By forbidding the use of exported names as identifiers for default exports, this rule encourages developers to use distinct names, improving the readability of the code. It makes it easier for developers to understand the structure of exports in a module, and thus, maintain the codebase more effectively.
-
Avoids potential errors in refactoring: With this rule, changing the name of a named export would not inadvertently affect the properties of the default export, and vice versa. This separation minimizes the risk of errors during refactoring processes, where changing the name of an export could lead to unintended consequences if the same name were used in multiple places.
-
Aligns with best practices in module design: The rule enforces a clear distinction between named exports and the default export of a module, which is considered a best practice in JavaScript module design. It encourages more deliberate naming conventions and export patterns that enhance the interoperability and composability of modules across a project.
Forbid named default exports.
// Bad: Importing a default export as if it were a named export.
import { default as ReactComponent } from 'react';
- Prevents confusion between named and default exports, which enhances code clarity and maintainability. For example, using
import { default as ReactComponent } from 'react';
can be misleading as it looks like a named import but actually is a default import. - Enforces a consistent import style across the codebase, making the code easier to read and refactor, by requiring that default exports are imported using the default import syntax (
import ReactComponent from 'react';
), rather than mimicking a named import syntax. - Reduces the potential for errors in the import statements, as misinterpreting a default import as a named import could lead to unnecessary complications or runtime errors in the code.
- Helps in upholding best practices for using ES6 module syntax, encouraging developers to use the most appropriate and semantically correct import statement for default exports, thereby promoting better coding standards within the team.
Forbid named exports.
// badExample.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
export function multiply(a, b) {
return a * b;
}
- Encourages the use of default exports over named exports which can simplify the import statements in modules that consume these exports, leading to more readable and maintainable code. By having a single default export, it reduces the complexity of handling multiple named exports across different files.
- Helps maintain a consistent codebase, especially in large projects where managing multiple named exports can become cumbersome. By enforcing the use of default exports, it becomes easier for developers to follow a uniform module structure across the project.
- Reduces the risk of naming conflicts in large projects. Named exports require importers to either use the exact name or rename them on import, which can lead to conflicts or confusion. Using a single default export avoids these issues by encapsulating all exports within a single namespace.
- Facilitates easier refactoring and scaling of the codebase. When using default exports, it is simpler to reorganize, add, or remove exported members without worrying about updating every import statement. This rule ensures that all exports are contained within a single object or function, making it more straightforward to modify exports without affecting the importers.
Forbid namespace (a.k.a. “wildcard” *
) imports.
// Bad: Using namespace import
import * as utils from "./utils";
const result = utils.add(1, 2);
console.log(result);
- Prevents indiscriminate import of all exported members from a module, which can lead to bloated bundle sizes in web applications as unused code is included.
- Encourages more explicit imports, making it easier for developers to understand at a glance which parts of a module are being used, thus improving code readability and maintainability.
- Reduces the potential for naming conflicts and ambiguity in the codebase since importing specific members requires either direct usage of their names or explicit aliasing, providing clearer scope and usage context.
- Facilitates better static analysis and tree shaking by explicitly specifying which imports are used, allowing bundlers and minifiers to easily exclude unused exports from the final bundle, leading to optimized application performance.
Forbid Node.js builtin modules.
// Example of bad code that violates the 'import/no-nodejs-modules' ESLint rule
import fs from 'fs';
function readConfigFile() {
let data = fs.readFileSync('/path/to/config.json', 'utf8');
return JSON.parse(data);
}
- Ensures the codebase is portable across environments that might not support Node.js native modules, making the application more versatile and adaptable to various platforms without requiring Node.js as a dependency.
- Encourages the use of browser-compatible alternatives for performing operations, which is particularly beneficial for projects intended to run in both Node.js and browser environments, fostering better practices for cross-environment compatibility.
- Helps in identifying and preventing the accidental inclusion of Node.js modules in frontend code, which could lead to runtime errors when the code is executed in environments that do not have these modules available, enhancing code robustness.
- Promotes the consideration and evaluation of lightweight, client-side libraries or APIs that can achieve similar functionality to Node.js modules, potentially leading to performance benefits in browser environments by avoiding the overhead of polyfills or server-side dependencies.
Forbid importing packages through relative paths.
// Assuming we're in a file located at /src/components/MyComponent.js
// Bad: Importing using relative paths
import utils from '../../utils/myUtilities';
import helper from '../helpers/myHelper';
- Prevents the complexity that comes with navigating through the project’s file structure using relative paths, which can become especially cumbersome in large projects. It ensures that the paths are clear and consistent regardless of where the file lives within the project.
- Enhances code readability and maintainability. When imports are made using absolute paths or aliases, it becomes immediately clear where the imported module is located in the project’s structure, avoiding the need to mentally parse relative paths.
- Facilitates easier refactoring and reorganization of project files. Since imports are not tied to the relative file structure, moving files around doesn’t require updating the import paths in multiple files, reducing the risk of breaking the application during restructuring.
- Encourages the use of a consistent and organized structure for project resources, by implicitly enforcing the definition and use of aliases or absolute paths. This can help in setting up clearer boundaries and separations of concerns within different parts of the project.
Forbid importing modules from parent directories.
// Assuming this file is at /project/src/components/MyComponent.js
// Bad: importing a utility from a parent directory
import utility from '../utils/utility';
function useUtility() {
return utility();
}
- Promotes the use of absolute paths over relative ones for importing modules from parent directories, leading to cleaner and more understandable code. This makes the codebase easier to navigate and maintain, especially in large projects where relative paths may become confusing.
- Encourages a more structured and modular code organization by disallowing imports from parent directories, compelling developers to think about the logical placement of modules. This could lead to better separation of concerns and a more scalable project architecture.
- Helps in preventing potential circular dependencies that could occur from indiscriminate relative imports. By forbidding imports from parent directories, it indirectly forces developers to structure their dependencies more thoughtfully, thus reducing the chance of creating tangled dependency graphs.
- Aids in making the codebase more portable and easier to refactor, as dependencies are encouraged to be structured in a manner that doesn’t rely on the relative positioning of modules. This means that moving parts of the code around to different locations within the project has a lesser chance of breaking imports.
Enforce which files can be imported in a given folder.
// File: /project/client/clientComponent.jsx
import serverUtils from '../server/serverUtils';
-
The rule helps maintain a clear separation of concerns within a project by enforcing restrictions on which files or folders can be imported into specific areas of the project. This reduces the risk of tightly coupling modules or layers that should ideally remain independent, such as importing server-side utilities directly into client-side components.
-
It mitigates potential runtime errors and deployment issues by preventing incorrect or unintended dependencies. For example, importing Node.js-specific modules into client-side code that is meant to run in a web browser environment can lead to errors that are only caught at runtime.
-
This rule allows for a more maintainable codebase by ensuring that imports follow the intended architectural patterns. By configuring restricted paths, teams can enforce specific import relationships and dependencies that align with their project’s architecture, making the code easier to understand and navigate.
-
It facilitates better code review and team collaboration by making it easier to spot violations of project structure conventions. When the rule is configured to reflect the project’s architectural guidelines, any imports that violate these guidelines will be automatically flagged, helping reviewers catch potential issues more efficiently.
Forbid a module from importing itself.
// example.js
import something from './example.js'; // This import violates the `import/no-self-import` rule.
function doSomething() {
console.log('Doing something.');
}
doSomething();
-
Prevents circular dependencies which can lead to runtime errors or infinite loops that are hard to debug. By ensuring a module doesn’t import itself, it reduces the risk of inadvertently creating a circular dependency within the application.
-
Improves code readability and maintainability by avoiding unnecessary and confusing import statements. When a developer sees an import statement, they expect that it imports external modules or other parts of the application, not the module itself.
-
Helps in better project organization by enforcing the rule to only import necessary and external modules or components. This encourages developers to think about the structure of their modules and how they are interconnected, leading to a more organized codebase.
-
Reduces unnecessary code bloat and potential performance impacts. Self-imports can lead to including the same module code multiple times if not handled properly by the bundler or the module system, potentially affecting the bundle size and load time negatively.
Forbid unassigned imports
import 'some-polyfill';
import './init-this-module';
function someFunction() {
console.log('This function requires the polyfill and module initialization to work properly.');
}
someFunction();
-
The ESLint rule
import/no-unassigned-import
specifically targets unassigned imports, which are imports that are pulled into the file but not assigned to a variable. This rule helps ensure that all imported modules are used within the code, promoting a cleaner and more readable codebase by eliminating unused code and potential side effects from unnecessary imports. -
By forbidding unassigned imports, except for those explicitly allowed through configuration options, this rule encourages developers to only include imports that are directly utilized. This practice can lead to more efficient bundling and loading of JavaScript files in a project since it discourages the inclusion of unnecessary code that could increase the size of JavaScript bundles and affect web application performance.
-
The rule allows for configuration to permit certain unassigned imports if needed, for example, polyfills or certain global styles that do not necessarily need to be assigned to a variable. This flexibility ensures that the rule can be tailored to the specific needs of a project, allowing for exceptions where unassigned imports are justified while still encouraging good import practices overall.
-
By enforcing the assignment of imports to identifiers, projects can benefit from easier tracking of module dependencies and exports throughout the application. This can simplify the process of debugging and refactoring, as it is clearer where and how imported modules are used. Additionally, it encourages the use of import statements for side effects only when absolutely necessary, which can lead to a more deliberate and thoughtful structuring of code dependencies and side effects.
Ensure imports point to a file/module that can be resolved.
// Trying to import a file that does not exist
import SomeNonexistentComponent from './components/SomeNonexistentComponent';
-
Prevents runtime errors related to non-existent modules by ensuring that all imported modules can actually be resolved to real files or packages, thus reducing bugs and potential crashes in the application during execution.
-
Enhances code reliability by detecting casing mismatches between import statements and the filesystem, important in environments where filename case sensitivity matters, preventing issues that could occur during deployment on case-sensitive systems like Linux when developed on case-insensitive systems like Windows.
-
Encourages better code organization and maintenance practices by ensuring all imports are valid, which could indirectly promote the removal of dead code and outdated dependencies that might linger when files or modules are moved or deleted.
-
Improves developer productivity by providing immediate feedback in the development environment about unresolved paths, reducing the time spent debugging issues related to incorrect or outdated import paths.
Forbid modules without exports, or exports without matching import in another module.
// utils.js
function add(a, b) {
return a + b;
}
- The rule helps identify modules in a codebase that are defined but never used, which helps in cleaning up and removing unnecessary code that could lead to confusion, or maintenance issues down the line. By ensuring every module has its exports used elsewhere, it enforces a practice of keeping only relevant code.
- By enforcing exports to have a corresponding import in some other module, it implicitly encourages developers to organize their codebase in a modular and reusable way, fostering best practices in code architecture and design.
- This rule assists in identifying potentially dead code paths early on. For instance, if a module’s exports are never imported, it’s a strong indicator that the module could be obsolete or its intended use case never materialized. Addressing such issues early can reduce the technical debt of a project.
- It supports a dynamic development environment by updating lists of existing exports and imports during runtime. This feature is particularly useful when working with tools like vscode-eslint, as it improves the accuracy of linting in a continuously changing codebase, ensuring that developers receive immediate feedback on their module usage.
Forbid unnecessary path segments in import and require statements.
import myModule from './path/to/../myModule';
const myOtherModule = require('../src/../myOtherModule');
- Enhances code readability and maintainability by eliminating unnecessary complexity in file paths, allowing developers to easily understand the structure of the project and the relationships between modules.
- Improves project consistency by enforcing a uniform way of referencing files, which helps in avoiding confusion among different developers working on the same project, especially in large codebases.
- Reduces the probability of errors related to incorrect paths or circular dependencies, by simplifying the import statements and making them more straightforward to write and review.
- Helps in potential performance optimization during the build process by streamlining the resolution of module paths, possibly leading to minor improvements in build and re-compilation times in large projects.
Forbid webpack loader syntax in imports.
// Trying to import a CSS file using the style-loader and css-loader
import styles from 'style-loader!css-loader!./styles.css';
- Ensures consistency in import statements by avoiding the mix of webpack loader syntax within them, helping maintain a uniform codebase.
- Prevents the coupling of build-specific loader configurations directly in code, allowing for a cleaner separation of concerns between build config and source code.
- Facilitates easier migration or configuration changes in the webpack setup without having to modify import statements across the entire project.
- Improves readability and maintainability of the code by keeping the import statements simple and focused solely on the modules being imported, rather than how they are processed.
Enforce a convention in module import order.
// React and utilities should be grouped and external libraries should come before internal imports
import myLocalComponent from './myLocalComponent';
import React from 'react';
import { map } from 'lodash';
import anotherLocalComponent from './anotherLocalComponent';
- This rule promotes consistent ordering of module imports, which can significantly enhance code readability and maintainability. By enforcing a convention on the sequence of imports, developers can quickly identify dependencies and understand how the modules are structured in relation to external libraries, built-in modules, and internal components.
- It allows for customizable configurations to align with team or project-specific guidelines, notably through options such as
newlines-between
,pathGroupsExcludedImportTypes
, and alphabetization settings. This flexibility ensures that the rule can be adapted to various coding standards and preferences, promoting adherence without compromising on individual or team practices. - The rule helps in reducing merge conflicts that can arise from differently ordered imports. When multiple developers are working on the same codebase, consistent ordering enforced by this rule can lower the chances of version control conflicts related to the arrangement of import statements, streamlining the development process.
- It includes the ability to automatically fix detected issues by reordering imports according to the specified configuration. This auto-fixing feature saves developers time by reducing manual effort required to comply with the import order convention and allows them to focus more on business logic rather than formatting concerns.
Prefer a default export if module exports a single name or multiple names.
// utils.js
export const utils = {
generateRandomNumber() {
return Math.random();
}
};
- Encourages consistency in module structure by advocating for a single default export in scenarios where only one entity is being exported. This makes it easier for developers to predict how modules are exported and imported across a codebase.
- Simplifies the import syntax for consumers of the module by allowing them to import without having to use curly braces or know the specific named exports, enhancing code readability and maintainability.
- By recommending default exports when there’s only a single export or multiple but preferred entities, it can potentially improve tree shaking in some bundling tools, as default exports are sometimes more efficiently tree-shaken compared to named exports.
- Helps in identifying and refactoring modules that unintentionally export more than what is necessary or what was intended by the developer, promoting better module API design and discouraging overly complex or unnecessary exports.
Forbid potentially ambiguous parse goal (script
vs. module
).
// example.js
function greet() {
console.log('Hello, world!');
}
greet();
-
Prevents Ambiguity in Parsing Goals: The rule is designed to forbid potentially ambiguous parse goals between scripts and modules, ensuring that JavaScript files are explicitly recognized as modules by tools that process them. This helps prevent confusion and errors in environments where both script and module sources are used.
-
Encourages Best Practices for Module Design: By enforcing the explicit declaration of exports in JavaScript files, the rule promotes the adoption of modular design patterns. This makes code more reusable and easier to manage, as dependencies are clearly stated.
-
Improves Tooling Compatibility: Tools like bundlers, linters, and transpilers rely on clear distinctions between scripts and modules to function correctly. By ensuring that files intended to be modules are unambiguously marked as such, the rule enhances compatibility and reduces the likelihood of build or runtime errors.
-
Facilitates Static Analysis and Optimization: When JavaScript files are unambiguously marked as modules, it is easier for static analysis tools to understand the structure of a codebase. This can lead to better optimization opportunities, more accurate code navigation, and improved refactoring capabilities, as the relationships between files are clearer.