Il messaggio di errore “Cannot use import statement outside a module” si verifica quando la parola chiave import viene riscontrata in un modulo JavaScript o TypeScript non correttamente configurato.

In un ambiente di runtime JavaScript lato server, questo errore si verifica solitamente a causa dell’uso della sintassi import per i moduli scritti in ECMAScript (ES) quando Node.js si aspetta la parola chiave require utilizzata dal sistema di moduli CommonJS.

TypeScript supporta diversi formati di moduli, ma anche gli errori di codifica che confondono gli approcci ES e CommonJS all’importazione dei moduli causano questo errore.

Per quanto riguarda il browser, l’errore si verifica in genere quando non si utilizza un bundler per i file di codice JavaScript.

Questo articolo esplora queste tre fonti di errore e descrive una soluzione per ogni ambiente.

Come risolvere l’errore in JavaScript lato server

Questa sezione mostra come risolvere l’errore in ambienti JavaScript lato server.

Contesto

Node.js utilizza la parola chiave require del sistema CommonJS per impostazione predefinita. Pertanto, riceverete il noto errore a meno che non configuriate Node.js per supportare la sintassi dei moduli ES. Allo stesso modo, Node.js richiede l’estensione .mjs per riconoscere e lavorare con i moduli ES.

Soluzione

In alternativa all’uso di .mjs, potete rendere le vecchie versioni di Node.js compatibili con il modulo ES corrente utilizzando i bundler o eseguendo Node.js con il flag --experimental-modules. Altrimenti, impostate il campo type nel file package.json a module come segue:

{
  "name": "test-package",
  "version": "1.0.0",
  "type": "module",
  "main": "app.js",
  "dependencies": { }
}

(Nota: dovreste includere la proprietà type nel file package.json in tutti i pacchetti. Questa pratica facilita l’identificazione del sistema di moduli in uso e garantisce la coerenza tra le vostre librerie).

Un altro modo per evitare l’errore è assicurarsi che le sintassi import e export siano corrette e vengano caricate correttamente. È fondamentale utilizzare sempre percorsi di file relativi, esportazioni con nome, estensioni di file per le esportazioni ed evitare esportazioni predefinite.

Ecco un esempio:

//module import 
import { sampleFunction } from './sampleModule.js';

// function export
export function sampleFunction() {
     // code goes here
}

Infine, dovrete assicurarvi della compatibilità di tutte le librerie di terze parti con i moduli ES. Per queste informazioni, consultate la documentazione della libreria nel file package.json. In alternativa, utilizzate un bundler per eseguire il transpiling del codice così che un ambiente JavaScript possa comprenderlo.

Come risolvere l’errore in ambienti TypeScript

Questa sezione mostra come risolvere il messaggio di errore negli ambienti TypeScript.

Contesto

Con i moduli è possibile riutilizzare, organizzare e condividere il codice tra più file di un progetto. ES supporta i moduli esterni per condividere il codice tra vari file utilizzando le parole chiave import e export.

Questo errore si verifica solitamente in ambienti TypeScript quando si utilizza la sintassi dei moduli ES senza configurare TypeScript per utilizzarla. Poiché TypeScript è un superset di JavaScript, per impostazione predefinita utilizza la sintassi CommonJS per le importazioni, che utilizza require invece di import. In questo caso, la dichiarazione import causa l’errore. Tuttavia, la corretta configurazione di TypeScript è necessaria per supportare i moduli ES.

Potreste riscontrare questo errore anche se utilizzate un’estensione di file non corretta. Ad esempio, se utilizzate TypeScript in un ambiente Node.js con la sintassi dei moduli ES, il modulo che desiderate importare deve avere l’estensione .mjs invece del normale .js.

Un’altra fonte comune di errore è la configurazione non corretta del campo module nei file tsconfig.json o package.json quando si utilizzano bundler come Webpack. Tuttavia, potete utilizzare i bundler per i moduli ES in TypeScript impostando i campi module e target nel file tsconfig.json su ECMAScript. In questo modo, Webpack capirà l’ambiente di destinazione e utilizzerà le estensioni di file corrette durante il transpiling del codice.

Soluzioni

Per caricare i moduli ES utilizzando un caricatore di moduli come RequireJS o un bundler come Webpack, eseguite le seguenti aggiunte al file tsconfig.json:

{
  "compilerOptions": {
    "module": "es20215",
    "target": "es20215",
    "sourceMap": true
  }
}

Nella porzione di codice compilerOptions, i campi module e target sono impostati per utilizzare un modulo es20215. Con queste aggiunte, potete utilizzare le dichiarazioni import e export in un ambiente TypeScript senza causare l’errore.

Poiché TypeScript utilizza CommonJS per impostazione predefinita, se non si modifica il file tsconfig.json di conseguenza, si otterrà il messaggio di errore.

Fortunatamente, una volta impostati i campi module e target per utilizzare un modulo ECMAScript, potete utilizzare lo statement export per esportare una funzione o una variabile da un modulo e lo statement import per caricare un altro modulo nell’ambito di quello corrente. Questo processo avviene nel codice sottostante:

// sum.ts
export function sum(a: number, b: number, c: number): number {
  return a + b + c;
}

// main.ts
import { sum } from './sum';
console.log(add(4, 4, 9));

Se utilizzate una versione precedente di Node.js, potete abilitare il supporto per i moduli ES eseguendo il codice con il flag --experimental-modules. Dovreste anche utilizzare un bundler come Webpack, Browserify o Rollup per raggruppare tutto il codice ES e inviarlo in un unico file. Assicuratevi che sia in una versione comprensibile ai browser e alle vecchie versioni di Node.js e impostate un file Webpack.config.js nella root del progetto che specifichi il tipo di modulo.

Ecco un esempio estratto dalla documentazione di Webpack:

module.exports = {
  entry: './src/index.ts',
  output: {
    filename: 'bundle.js',
   path: path.resolve(__dirname, 'dist')
  },
  resolve: {
    extensions: ['.ts', '.js', '.mjs']
  },
  module: {
    rules: [
      {
        test: /.ts$/,
        use: 'ts-loader',
        exclude: /node_modules/
      }
    ]
  },
  experiments: {
    outputModule: true
  }
};

Il codice compilato viene inviato a un file bundle.js nella directory dist della cartella principale del progetto.

Potete anche utilizzare polyfill come es-module-shims per indirizzare i browser più vecchi che non supportano le dichiarazioni import e export dei moduli ES.

Come risolvere l’errore in Browser-Side JavaScript

Questa sezione mostra come risolvere l’errore negli ambienti JavaScript lato browser.

Contesto

La maggior parte dei browser moderni, tra cui Chrome, Firefox, Edge e Safari, supportano i moduli ES, quindi non è necessario utilizzare polyfill, bundler o transpiler del browser.

Non ne avrete bisogno nemmeno se utilizzate le librerie frontend basate su React o Vue JavaScript perché supportano i campi ES imports e exports per impostazione predefinita. Tuttavia, i browser più vecchi non supportano la sintassi ES e quindi richiedono questi strumenti per la compatibilità multipiattaforma.

Il motivo più frequente per cui si verifica l’errore nei browser più vecchi è quando i file HTML di una pagina non contengono l’attributo type="module". In questo caso, l’errore si verifica perché JavaScript in esecuzione sul web non include il supporto predefinito per la sintassi del modulo ES. Per il codice JavaScript inviato via wire, potreste riscontrare un errore di condivisione delle risorse di origine incrociata quando tentate di caricare un modulo ES da un dominio diverso.

Soluzione

Per evitare l’errore del modulo nei browser più vecchi, assicuratevi di utilizzare l’attributo corretto del tag scripttype="module" – nel file HTML principale. In alternativa, potete usare Webpack per eseeguire il transpiling del codice in modo che i browser più vecchi possano comprenderlo.

Per utilizzare l’attributo type="module", includete la seguente riga nel file HTML principale:

<script type="module" src="app.js"></script>

È altrettanto importante assicurarsi che i percorsi dei file import siano validi e che si utilizzi la sintassi import corretta.

Inoltre, potete visitare siti come Can I Use per verificare la compatibilità dei browser con i moduli ES.

Infine, poiché l’uso dell’estensione .js è una pratica comune, potete impostare l’attributo type nel tag script del file HTML del modulo come soluzione alternativa. Impostando questo attributo a module, il browser dovrà ignorare l’estensione .js e trattare il file come un modulo.

Riepilogo

L’errore “Cannot use import statement outside a module” può comparire per vari motivi, a seconda che siate in un ambiente JavaScript lato browser o lato server. Sintassi errata, configurazioni improprie ed estensioni di file non supportate sono solo alcune delle fonti più comuni di questo errore.

Sebbene la maggior parte dei browser moderni supporti i moduli ES, dovete assicurarvi che i browser più vecchi siano compatibili. I bundler come Webpack permettono di compilare tutto il codice sorgente con le relative dipendenze in un unico output comprensibile ai browser più vecchi.

Ricordate di aggiungere l’attributo type="module" nel file HTML per informare il browser che il modulo è un modulo ES. Infine, mentre l’utilizzo dell’estensione .js per CommonJS è la prassi predefinita, potete utilizzare l’estensione .mjs per consentire l’importazione dei moduli ES.

Avete un’applicazione JavaScript da mandare online ma non volete gestire i server in prima persona? Le piattaforme di Hosting di Applicazioni e Hosting di Database di Kinsta potrebbero fare al caso vostro. Potreste anche combinare questi servizi con l’Hosting di Siti Statici di Kinsta per avere il front-end della vostra applicazione gratuitamente.