No side effects on import
Why it matters
Code that executes at import time bypasses the consumer's control plane. A top-level fetch() fires before the consumer has configured anything; a top-level console.log pollutes test output and server logs; a globalThis mutation can conflict with other packages or the host environment. ISO 25010 compatibility and fault-tolerance both degrade when a package modifies global state the moment it's imported. In server-side rendering, side-effecting imports can crash the render pass. In test environments, they produce flaky behavior depending on import order.
Severity rationale
Critical because side effects on import execute before the consumer opts in, enabling silent global mutations, unsolicited network calls, and SSR crashes that are invisible until production.
Remediation
Move all initialization into exported constructors or factory functions. Nothing should run at module evaluation time.
// Before — side effects on import:
console.log('SDK loaded')
globalThis.__SDK = true
const config = await fetch('/api/config') // this fires on every import
// After — no side effects, consumer controls initialization:
export class Client {
constructor(private config: ClientConfig) {
// initialization here, when the consumer asks for it
}
}
Also declare in package.json:
{ "sideEffects": false }
This tells webpack, Rollup, and Vite that all modules are safe to tree-shake. If any files have legitimate side effects (CSS imports, polyfills), list only those files in the sideEffects array.
Detection
-
ID:
no-side-effects -
Severity:
critical -
What to look for: Count all module-level statements in the SDK entry point and public modules. For each, classify whether it causes side effects on import. examine the main entry point file and any files it imports (follow the import chain). Look for code that executes at import time:
- Top-level
fetch(),axios(), or HTTP calls - Top-level
console.log(),console.warn(), or other logging - Top-level
addEventListener()or DOM manipulation - Top-level
setInterval()orsetTimeout() - Top-level mutations to
global,window,process, orglobalThis - Importing for side effects (
import './polyfill',import './register') - Module-level code that reads from the filesystem or environment
Also check
package.jsonfor"sideEffects": falsedeclaration.
- Top-level
-
Pass criteria: Importing the package does not execute any observable side effects. All functionality is behind exported functions or class constructors that must be explicitly called. The package may declare
"sideEffects": falseinpackage.json(recommended but not required for pass) — 100% of imports must be side-effect-free unless explicitly documented. Report: "X module-level statements found, Y are side-effect-free." -
Fail criteria: The entry point or its immediate imports execute code at module evaluation time — logging, network requests, global mutations, polyfills, or event listeners that run when someone does
import 'your-package'. -
Skip (N/A) when: The package is explicitly designed to be a polyfill, shim, or registration side-effect (e.g.,
@babel/register, CSS reset packages). Thepackage.jsondescription or README must indicate this intent. -
Detail on fail:
"src/index.ts has a top-level console.log('SDK initialized') and sets global.__SDK_VERSION. These execute when the package is imported, before the consumer has opted in. A fetch() call to the package telemetry endpoint also runs at import time." -
Remediation: Side effects on import surprise consumers, break tree-shaking, and cause problems in test environments and server-side rendering.
// Before — side effects on import: console.log('MySDK v1.0.0 loaded') globalThis.__MY_SDK = true const config = await fetch('/api/config') export class Client { /* ... */ } // After — no side effects, everything is explicit: export class Client { constructor(config: ClientConfig) { // initialization happens here, when the consumer asks for it } } export function getVersion() { return '1.0.0' }Also add to
package.json:{ "sideEffects": false }
External references
- iso-25010:2011 · compatibility.interoperability — Interoperability — import-time side effects break SSR and test environments
- iso-25010:2011 · reliability.fault-tolerance — Fault tolerance — unexpected side effects on import cause failures in constrained environments
Taxons
History
- 2026-04-18·v1.0.0·Initial import from sdk-package-quality·automated