So beheben Sie 'Cannot use import statement outside a module'
Sie schreiben eine saubere import-Anweisung, führen Ihren Code aus und stoßen sofort auf diese Fehlermeldung:
SyntaxError: Cannot use import statement outside a module
Dieser JavaScript-ES-Modul-Fehler ist eine der häufigsten Ursachen für Verwirrung bei Entwicklern, die mit Node.js, Browsern und Testumgebungen arbeiten. Die Lösung ist nicht immer dieselbe – und die Anwendung der falschen macht alles nur schlimmer. Hier erfahren Sie, wie Sie Ihre Situation diagnostizieren und korrekt beheben können.
Wichtigste Erkenntnisse
- Dieser Fehler ist eine Inkompatibilität des Modulsystems, kein Syntaxfehler – Ihre Laufzeitumgebung erwartete CommonJS, stieß aber auf ES-Modul-
import-Syntax. - In Node.js setzen Sie
"type": "module"inpackage.jsonoder verwenden Sie die.mjs-Dateierweiterung, um ESM zu aktivieren. - In Browsern fügen Sie
type="module"zu Ihrem<script>-Tag hinzu, damit die Engine die Datei als ES-Modul behandelt. - In Jest konfigurieren Sie Babel, um ESM in CommonJS zu transformieren, und passen Sie
transformIgnorePatternsfür ESM-only-Drittanbieterpakete an. - Diagnostizieren Sie immer zuerst Ihre Umgebung – Node.js, Browser oder Test-Runner – bevor Sie eine Lösung anwenden.
Warum dieser Fehler auftritt
Der Fehler bedeutet, dass Ihre Laufzeitumgebung auf ES-Modul-Syntax (import) gestoßen ist, aber etwas anderes erwartete – normalerweise CommonJS (require). Es handelt sich um eine Inkompatibilität des Modulsystems, nicht um einen Syntaxfehler in Ihrem Code.
JavaScript hat zwei Modulsysteme:
| System | Syntax | Standard in |
|---|---|---|
| CommonJS (CJS) | require() | Node.js (Legacy) |
| ES Modules (ESM) | import | Browser, modernes Node.js |
Die Laufzeitumgebung entscheidet anhand der Konfiguration, welches System verwendet wird – nicht anhand des Codes selbst. Deshalb funktioniert dieselbe import-Anweisung in einem Projekt und schlägt in einem anderen fehl.
So beheben Sie den Fehler “Import Statement Outside Module” in Node.js
Node.js behandelt .js-Dateien als CommonJS, es sei denn, "type": "module" ist in package.json gesetzt. Um import zu verwenden, müssen Sie sich explizit für ESM entscheiden.
Option 1: Setzen Sie "type": "module" in package.json
{
"name": "my-app",
"version": "1.0.0",
"type": "module"
}
Dies teilt Node.js mit, alle .js-Dateien im Projekt als ES-Module zu behandeln. Siehe die offizielle Node.js ES-Module-Dokumentation für Details darüber, wie Node den Modultyp bestimmt.
Option 2: Verwenden Sie die .mjs-Dateierweiterung
Benennen Sie Ihre Datei von app.js in app.mjs um. Node.js behandelt .mjs-Dateien immer als ESM, unabhängig von package.json.
Option 3: Verwenden Sie .cjs für CommonJS-Dateien
Wenn Ihr Projekt "type": "module" verwendet, aber eine Datei require() benötigt, geben Sie ihr eine .cjs-Erweiterung.
Wichtig: Fügen Sie nicht einfach
"type": "module"hinzu, ohne Ihre anderen Dateien zu überprüfen. Jede Datei, dierequire(),module.exportsoder__dirnameverwendet, wird unter ESM nicht funktionieren.
Behebung des Fehlers in Browser-JavaScript
In Browsern funktioniert statisches import nur innerhalb eines Modul-Scripts. Wenn Ihr <script>-Tag nicht type="module" deklariert, behandelt der Browser es als klassisches Script und lehnt die import-Syntax ab.
<!-- Dies wird den Fehler auslösen -->
<script src="app.js"></script>
<!-- Dies funktioniert -->
<script type="module" src="app.js"></script>
Dieses Verhalten ist Teil der standardmäßigen JavaScript-Module-Spezifikation, die von modernen Browsern implementiert wird.
Beachten Sie, dass Modul-Scripts gekapselt sind – Variablen, die darin deklariert werden, sind nicht global verfügbar. Deshalb könnte es sein, dass Sie type="module" hinzufügen und dann einen ReferenceError für eine Variable sehen, von der Sie erwarteten, dass sie global ist. Die Lösung besteht darin, Werte explizit zu exportieren und zu importieren, anstatt sich auf den globalen Scope zu verlassen.
Discover how at OpenReplay.com.
Behebung des Fehlers in Jest und anderen Testumgebungen
Jest läuft in Node.js und verwendet traditionell standardmäßig CommonJS, selbst wenn Ihr Quellcode ESM verwendet. Dies ist eine häufige Ursache für den Fehler “cannot use import statement outside a module” in Test-Suites.
Ein Ansatz besteht darin, Babel so zu konfigurieren, dass ESM während des Testens in CommonJS transformiert wird:
// babel.config.js
module.exports = {
presets: ['@babel/preset-env'],
}
Alternativ kann Jest so konfiguriert werden, dass Tests im nativen ESM-Modus ausgeführt werden, wenn Ihr Projekt bereits ES-Module verwendet. Siehe die Jest ECMAScript Modules-Dokumentation für Details.
Wenn ein Drittanbieterpaket (wie swiper, lodash-es oder ähnliche ESM-only-Bibliotheken) den Fehler verursacht, müssen Sie Jest mitteilen, es zu transformieren, anstatt es zu ignorieren:
// jest.config.js
module.exports = {
transformIgnorePatterns: [
'/node_modules/(?!(swiper|ssr-window|dom7)/)',
],
}
Die wichtigste Erkenntnis: transformIgnorePatterns verwendet einen negativen Lookahead. Sie sagen: “Ignoriere alles in node_modules außer diesen Paketen.” Das Auflisten in separaten Array-Einträgen funktioniert nicht – sie müssen in einem einzigen Regex-Muster mit | kombiniert werden.
TypeScript-Konfiguration
Wenn Sie TypeScript verwenden, überprüfen Sie Ihre tsconfig.json. Das Feld module steuert, welche Modulsyntax TypeScript in seiner kompilierten Ausgabe erzeugt:
{
"compilerOptions": {
"module": "ESNext",
"target": "ESNext"
}
}
Das Setzen von module auf CommonJS beim Schreiben von import-Anweisungen ist gültiges TypeScript – der Compiler transformiert import in require() in der Ausgabe. Das Setzen von module auf ESNext beim Ausführen der Ausgabe in einer CommonJS-Node.js-Umgebung (ohne "type": "module" in package.json) wird jedoch den Fehler zur Laufzeit auslösen. Stellen Sie sicher, dass Ihre tsconfig.json-Moduleinstellung mit dem übereinstimmt, was Ihre Laufzeitumgebung tatsächlich erwartet.
Diagnostizieren Sie, bevor Sie beheben
Derselbe Fehler tritt in verschiedenen Umgebungen aus verschiedenen Gründen auf. Bevor Sie eine Lösung anwenden, fragen Sie sich:
- Wo tritt der Fehler auf – Node.js, Browser oder Test-Runner?
- Was sagt Ihr
package.json-Feld"type"? - Verwenden Sie einen Bundler oder führen Sie Dateien direkt aus?
Die Beantwortung dieser drei Fragen führt Sie jedes Mal zur richtigen Lösung.
Häufig gestellte Fragen (FAQs)
Ja, aber Sie müssen Dateierweiterungen verwenden, um sie zu unterscheiden. Dateien mit einer .mjs-Erweiterung werden immer als ES-Module behandelt, und Dateien mit einer .cjs-Erweiterung werden immer als CommonJS behandelt, unabhängig vom type-Feld in package.json. Dies ermöglicht es Ihnen, beide Systeme nebeneinander in einem einzigen Projekt zu verwenden.
Nein. Jedes Paket in node_modules hat seine eigene package.json, sodass Ihr type-Feld nur für Ihre Projektdateien gilt. Abhängigkeiten definieren ihr eigenes Modulsystem unabhängig. Der Fehler kommt normalerweise von Ihren eigenen Dateien oder vom Import einer ESM-only-Abhängigkeit in einem CommonJS-Kontext ohne ordnungsgemäße Transformation.
Bundler wie Webpack und Vite verarbeiten import-Anweisungen während des Build-Schritts und erzeugen eine einzige Ausgabedatei. Sie lösen die Modulsyntax auf, bevor die Laufzeitumgebung sie überhaupt sieht. Wenn Sie Dateien direkt in Node.js oder einem Browser ohne Bundler ausführen, muss die Laufzeitumgebung selbst das Modulformat verstehen, was zu Inkompatibilitäten führt, die diesen Fehler verursachen.
Diese CommonJS-Globals sind in ES-Modulen nicht verfügbar. Stattdessen können Sie sie mit import.meta.url rekonstruieren. Verwenden Sie beispielsweise new URL(import.meta.url).pathname, um den Dateipfad zu erhalten, oder kombinieren Sie es mit dem path-Modul und fileURLToPath aus dem url-Modul, um das __dirname-Verhalten nachzubilden.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.