Codeausschnitt Next.JS Komponente

Next.js ist eine sehr gute Möglichkeit, um eine Full-stack Anwendung auf Basis des React-Frameworks in Javascript oder Typescript aufzubauen. Größter Vorteil ist, dass die Komponenten serverseitig vorbereitet (“gerendert”) werden, so dass die Webseite auch von Suchmaschinen gefunden werden kann.

Genau diese Methode kann aber auch gelegentlich zu Problemen führen, insbesondere, wenn man fertige Module einbinden möchte, die nur im Browser ausgeführt werden können. In meinem Fall war dies das Modul “swagger-ui-react”, mit dem ich die Beschreibung meiner REST-API in anschaulicher Form als Webseite bereitstellen kann. Dieses fertige Modul lässt sich in der aktuellen Version nicht auf dem Server rendern.

Mein erster Versuch war also, das Modul als einfache Komponente bereitzustellen, die Daten meiner API liegen dabei als JSON Datei vor. Hier meine Komponente, wie sie bei klassischen React Webseiten funktioniert:

import SwaggerUI from "swagger-ui-react";
import "swagger-ui-react/swagger-ui.css";
import swaggerDocument from "../meine-api.json";

export default function ApiDocs() {
  return <SwaggerUI spec={swaggerDocument} />;
}

Im Next.JS Framework versucht das System nun aber, diese Komponente vor der Auslieferung an den Browser bereits auf dem Server aufzubereiten. Das schlägt fehl, da die fertige Komponente nicht dafür ausgelegt ist.

Es kommt zu einer sehr umfangreichen Fehlermeldung, deren hervorgehobene Kernaussage ist: “Cannot use import statement outside a module” – kann außerhalb eines Moduls keinen Import verwenden.

Leider ist diese Formulierung nicht wirklich zielführend. Bei meiner Suche bin ich zwar häufig auf die gleiche Fehlermeldung gestoßen, aber die vorgeschlagenen Lösungswege waren oft wenig bis gar nicht hilfreich.

Nach längerer Suche und Studium der Next Dokumentation bin ich auf die “dynamic” Bibliothek in Next gestoßen, die schlussendlich die Lösung gebracht hat. Durch diese Methode wird das Laden der eigentlichen SwaggerUI Bibliothek verzögert, mit zusätzlichem Parameter { ssr: false } sogar ganz auf die Client-Seite verlagert, so dass der Code nun – wie erwünscht – auf dem Browser des Anwenders ausgeführt wird.

Der Clou ist also, die Bibliothek “SwaggerUI” nicht direkt in der Kopfzeile des Moduls zu importieren, sondern erst zur Laufzeit – und dem System dann noch ausdrücklich mitzuteilen, dass die Ausführung bitte nicht auf dem Server, sondern beim Anwender stattfinden soll.

Hier ist die funktionierende Lösung:

import dynamic from "next/dynamic";
import swaggerDocument from "../meine-api.json";
import "swagger-ui-react/swagger-ui.css";

const SwaggerUI = dynamic(
  () => import("swagger-ui-react"), { ssr: false }
);

export default function ApiDocs() {
  return <SwaggerUI spec={swaggerDocument} />;
}

Fazit: Der größte Vorteil der Next.JS Bibliothek, die Aufbereitung der dynamischen Webseiten auf dem Server, kann auch zum Nachteil werden, wenn man eine Bibliothek aus fremder Quelle einbindet, die dafür nicht vorgesehen ist. Hier hilft nur, die Ausführung wieder auf den Browser des Anwenders zu verlegen. Kleine, aber effektive Lösung nach langer Suche.

Links:

Offizielle Next.js Dokumentation zu “dynamic”: https://nextjs.org/docs/advanced-features/dynamic-import#with-no-ssr

Swagger-UI webseite: https://swagger.io/tools/swagger-ui/

NPM Modul: https://www.npmjs.com/package/swagger-ui

2 Kommentare zu “wie man den “Cannot use import statement outside a module” – Fehler in Next.js behebt

  1. Ich möchte mich herzlich bedanken für diesen Blog Artikel! Der Artikel hat mir nun neue Erkenntnisse gebracht. Ich freue mich schon darauf, weitere Artikel von euch zu lesen.
    LG

  2. Dieser Artikel hat viele meiner Fragen zum Thema „wie man den “Cannot use import statement outside a module” – Fehler in Next.js behebt“ beantwortet. Ich habe den Artikel sehr gerne gelesen und interessante Ideen daraus schöpfen können. Macht weiter so und schreibt interessante Artikel über IT-Themen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert