How to fix ESM syntax requires file extension, got import "module" in React

ReactBEGINNERMEDIUMUpdated Dec 11, 2025ยท 188 views

This error occurs when importing modules without file extensions in Vite projects. Node.js ESM requires explicit file extensions in all import statements, and Vite enforces this standard.

Quick fix

Fixes ESM syntax requires file extension, got import "module"

import MyComponent from './MyComponent'
import { helper } from '../utils/helpers'
import './styles.css'
  1. Add file extensions to all local imports
  2. Use correct extensions for TypeScript files
  3. Check for extensionless imports in barrel files
  4. Configure TypeScript for ESM compatibility (if using TypeScript)
react โ€” error
import MyComponent from './MyComponent'
import { helper } from '../utils/helpers'
import './styles.css'
ESM syntax requires file extension, got import "module"

What this error means

This error is thrown by Vite when you attempt to import a local module without specifying its file extension. Unlike bundlers like webpack that allow extensionless imports, Vite strictly follows Node.js ESM (ECMAScript Modules) specifications, which require full file paths including extensions. In Node.js ESM, relative import paths must include the complete file extension (e.g., `.js`, `.ts`, `.jsx`, `.tsx`, `.vue`, `.css`). This is a fundamental requirement of how ESM works in Node.js, not a Vite-specific limitation. The restriction ensures that module resolution is explicit and predictable. When Vite encounters an import statement like `import { helper } from './utils'` instead of `import { helper } from './utils.js'`, it cannot resolve the module and throws this error. This applies to all local file imports in your project, including components, utilities, and stylesheets.

Typical symptoms

  • Build fails with "ESM syntax requires file extension" error message
  • Development server crashes when starting or hot-reloading
  • Import statements that worked in webpack-based projects fail in Vite
  • Error specifically mentions missing file extension for a particular import
  • SSR mode or Vitest tests fail with module resolution errors

Common causes

  1. Importing local modules without file extensions (e.g., import "./component" instead of import "./component.jsx")
  2. Migrating from webpack-based projects where extensionless imports were allowed
  3. Using third-party libraries that contain extensionless imports in their ESM builds
  4. Copying import statements from documentation that assumes CommonJS or webpack module resolution
  5. TypeScript configuration expecting different module resolution behavior

How to fix "ESM syntax requires file extension, got import "module""

1Add file extensions to all local imports

Review your import statements and add the appropriate file extension to each local module import.

Before:

javascript
import MyComponent from './MyComponent'
import { helper } from '../utils/helpers'
import './styles.css'

After:

javascript
import MyComponent from './MyComponent.jsx'
import { helper } from '../utils/helpers.js'
import './styles.css'  // CSS imports already include extension

Note: Package imports (from node_modules) do not require extensions, only relative/absolute file paths do.

2Use correct extensions for TypeScript files

When importing TypeScript files in a Vite project, you have two options:

Option 1: Use .ts/.tsx extensions (recommended for Vite):

typescript
import { MyType } from './types.ts'
import MyComponent from './MyComponent.tsx'

Option 2: Use .js/.jsx extensions (Node.js ESM standard):

typescript
// Import with .js even though source file is .ts
import { MyType } from './types.js'
import MyComponent from './MyComponent.jsx'

While Node.js ESM technically expects .js extensions (since TypeScript compiles to JavaScript), Vite's dev server handles .ts/.tsx extensions natively, so using the actual source file extension is more straightforward.

3Check for extensionless imports in barrel files

Barrel files (index.ts/index.js) that re-export multiple modules are common sources of this error.

Before:

javascript
// src/components/index.js
export { default as Button } from './Button'
export { default as Input } from './Input'

After:

javascript
// src/components/index.js
export { default as Button } from './Button.jsx'
export { default as Input } from './Input.jsx'

Search your codebase for these patterns:

bash
grep -r "from '\./" src/
grep -r 'from "\../' src/
4Configure TypeScript for ESM compatibility (if using TypeScript)

Update your tsconfig.json to work with ESM module resolution:

json
{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "bundler",  // Vite-compatible resolution
    "allowImportingTsExtensions": true,
    "noEmit": true  // Vite handles compilation
  }
}

For Node.js 16+ compatibility in SSR scenarios:

json
{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "node16"  // or "nodenext"
  }
}

With node16 or nodenext, TypeScript will require .js extensions even for .ts source files.

5Handle third-party libraries with extensionless imports

If a third-party library in node_modules has extensionless imports in its ESM build, you have limited options:

Option 1: Use a CommonJS version (if available):
Check the library's package.json for a CommonJS export and configure Vite to use it:

javascript
// vite.config.js
export default {
  resolve: {
    alias: {
      'problematic-lib': 'problematic-lib/dist/cjs/index.js'
    }
  }
}

Option 2: Report the issue to the library maintainers - ESM builds should include file extensions per Node.js spec.

Option 3: Use optimizeDeps to pre-bundle the dependency:

javascript
// vite.config.js
export default {
  optimizeDeps: {
    include: ['problematic-lib']
  }
}
6Verify package.json type field for SSR projects

If you're using Vite for SSR (server-side rendering), ensure your package.json correctly declares the module type:

json
{
  "type": "module"
}

This tells Node.js to treat .js files as ESM. Without this field, Node.js defaults to CommonJS and will reject ESM syntax entirely.

If you need to mix CommonJS and ESM, use explicit file extensions:
- .mjs for ES modules
- .cjs for CommonJS modules
- .js behavior determined by package.json "type" field

Advanced notes

Why does Node.js ESM require file extensions?

The ESM specification requires explicit file extensions to avoid ambiguity and filesystem operations during module resolution. Unlike CommonJS (which tries .js, .json, .node extensions automatically), ESM resolution must be deterministic and fast. This design decision eliminates the need for expensive filesystem lookups and makes module resolution predictable across different environments.

Webpack vs. Vite module resolution:

Webpack provides "magic" module resolution that tries multiple extensions and directory indexes automatically. Vite deliberately does not replicate this behavior in its dev server because it follows Node.js ESM semantics. However, Vite's build (using Rollup) does provide some automatic resolution. This inconsistency between dev and build can sometimes cause confusion.

TypeScript's .js extension requirement:

TypeScript expects you to write .js extensions in import statements even when importing .ts files, because the compiled output will be .js. This can feel counterintuitive in Vite, where you can import .ts files directly. The moduleResolution: "bundler" option tells TypeScript to accept Vite's behavior.

Performance implications:

Explicit file extensions significantly improve cold-start performance in development. Vite doesn't need to stat multiple file paths for each import, making the dev server extremely fast. This is one of the core reasons Vite is faster than webpack-based dev servers.

Frequently asked questions

What does "ESM syntax requires file extension, got import "module"" mean?
This error is thrown by Vite when you attempt to import a local module without specifying its file extension. js ESM (ECMAScript Modules) specifications, which require full file paths including extensions. css).
How do I fix "ESM syntax requires file extension, got import "module""?
This error occurs when importing modules without file extensions in Vite projects. Node.js ESM requires explicit file extensions in all import statements, and Vite enforces this standard.
What causes "ESM syntax requires file extension, got import "module""?
Importing local modules without file extensions (e.g., import "./component" instead of import "./component.jsx") Migrating from webpack-based projects where extensionless imports were allowed Using third-party libraries that contain extensionless imports in their ESM builds
Is the "ESM syntax requires file extension, got import "module"" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading