Le message d’erreur « Cannot use import statement outside a module » se produit lorsque le mot-clé import est rencontré dans un module JavaScript ou TypeScript mal configuré.

Dans un environnement d’exécution JavaScript côté serveur, cette erreur résulte généralement de l’utilisation de la syntaxe import pour les modules écrits en ECMAScript (ES) alors que Node.js attend le mot-clé require utilisé par le système de modules CommonJS.

TypeScript prend en charge différents formats de modules, mais les erreurs de codage qui confondent les approches ES et CommonJS de l’importation de modules entraînent également cette erreur.

Du côté du navigateur, l’erreur se produit généralement lorsque vous n’utilisez pas de bundler pour vos fichiers de code JavaScript.

Cet article explore ces trois sources d’erreur et détaille une solution pour chaque environnement.

Comment résoudre l’erreur dans le JavaScript côté serveur

Cette section montre comment résoudre l’erreur dans les environnements JavaScript côté serveur.

Contexte

Node.js utilise par défaut le mot-clé require du système CommonJS. Par conséquent, vous recevrez l’erreur habituelle à moins que vous ne configuriez Node.js pour qu’il prenne en charge la syntaxe des modules ES. De même, Node.js a besoin de l’extension .mjs pour reconnaître et utiliser les modules ES.

Solution

Au lieu d’utiliser .mjs, vous pouvez rendre les anciennes versions de Node.js compatibles avec le module ES actuel en utilisant des bundlers ou en exécutant Node.js avec le drapeau --experimental-modules. Sinon, vous pouvez définir le champ type dans le fichier package.json à module comme suit :

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

(Remarque : vous devez inclure la propriété type dans le fichier package.json pour tous les paquets. Cette pratique facilite l’identification du système de modules utilisé et garantit la cohérence de vos bibliothèques)

Une autre façon d’éviter l’erreur est de s’assurer que les syntaxes import et export sont correctes et se chargent correctement. Il est essentiel de toujours utiliser des chemins de fichiers relatifs, des exportations nommées, des extensions de fichiers pour les exportations et d’éviter les exportations par défaut.

Voici un exemple :

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

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

Enfin, vous devez vous assurer de la compatibilité de toutes les bibliothèques tierces avec les modules ES. Pour cela, reportez-vous à la documentation de la bibliothèque dans le fichier package.json. Vous pouvez également utiliser un bundler pour transpiler le code afin qu’un environnement JavaScript puisse le comprendre.

Comment résoudre l’erreur dans les environnements TypeScript

Cette section montre comment résoudre le message d’erreur dans les environnements TypeScript.

Contexte

Les modules vous permettent de réutiliser, d’organiser et de partager du code entre plusieurs fichiers d’un projet. ES prend en charge les modules externes pour le partage de code entre différents fichiers à l’aide des mots-clés import et export.

Cette erreur se produit généralement dans les environnements TypeScript lorsque vous utilisez la syntaxe de module ES sans configurer TypeScript pour l’utiliser. TypeScript étant un sur-ensemble de JavaScript, il utilise par défaut la syntaxe CommonJS pour les importations, qui utilise require au lieu de import. Dans ce cas, c’est l’instruction import qui est à l’origine de l’erreur. Néanmoins, il est nécessaire de configurer correctement TypeScript pour qu’il prenne en charge les modules ES.

Vous pouvez également rencontrer cette erreur si vous utilisez une extension de fichier incorrecte. Par exemple, lorsque vous utilisez TypeScript dans un environnement Node.js avec la syntaxe des modules ES, le module que vous souhaitez importer doit avoir l’extension de fichier .mjs au lieu de l’extension normale .js.

Une autre source d’erreur courante est la mauvaise configuration du champ module dans vos fichiers tsconfig.json ou package.json lorsque vous utilisez des bundlers comme Webpack. Cependant, vous pouvez utiliser des bundlers pour les modules ES en TypeScript en définissant les champs module et target dans le fichier tsconfig.json à ECMAScript. Webpack comprendra alors l’environnement cible et utilisera les extensions de fichier correctes lors de la transpilation du code.

Solution

Pour charger des modules ES à l’aide d’un chargeur de modules comme RequireJS ou d’un bundler comme Webpack, ajoutez les éléments suivants au fichier tsconfig.json:

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

Dans la partie compilerOptions du code ci-dessus, les champs module et target sont définis pour utiliser un module es20215. Grâce à ces ajouts, vous pouvez utiliser les déclarations import et export dans un environnement TypeScript sans provoquer d’erreur.

Comme TypeScript utilise CommonJS par défaut, si vous ne modifiez pas le fichier tsconfig.json en conséquence, vous obtiendrez le message d’erreur.

Heureusement, une fois que vous avez défini les champs module et target pour utiliser un module ECMAScript, vous pouvez utiliser l’instruction export pour exporter une fonction ou une variable d’un module et l’instruction import pour charger un autre module dans la portée du module actuel. C’est ce qui se passe dans le code ci-dessous :

// 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));

Si vous utilisez une version plus ancienne de Node.js, vous pouvez activer la prise en charge des modules ES en exécutant votre code avec l’option --experimental-modules. Vous devez également utiliser un bundler comme Webpack, Browserify ou Rollup pour regrouper tout le code ES et le publier dans un seul fichier. Assurez-vous qu’il s’agit d’une version que les navigateurs et les anciennes versions de Node.js peuvent comprendre et mettez en place un fichier Webpack.config.js à la racine de votre projet qui spécifie le type de module.

Voici un exemple extrait de la documentation de 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
  }
};

Le code compilé est envoyé dans un fichier bundle.js dans le répertoire dist du répertoire racine du projet.

Vous pouvez également utiliser des polyfills comme es-module-shims pour cibler les anciens navigateurs qui ne prennent pas en charge les déclarations import et export des modules ES.

Comment résoudre l’erreur dans le JavaScript côté navigateur

Cette section vous montre comment résoudre l’erreur dans les environnements JavaScript côté navigateur.

Contexte

La plupart des navigateurs modernes, notamment Chrome, Firefox, Edge et Safari, prennent en charge les modules ES. Vous n’aurez donc pas besoin d’utiliser les polyfills, les bundlers ou les transpilers des navigateurs.

Vous n’en aurez pas besoin non plus si vous utilisez les bibliothèques frontend JavaScript React ou Vue, car elles prennent en charge par défaut les champs ES imports et exports. Toutefois, les navigateurs plus anciens ne prennent pas en charge la syntaxe ES et ont donc besoin de ces outils pour assurer la compatibilité entre les plateformes.

La raison la plus fréquente de l’erreur dans un navigateur plus ancien est que les fichiers HTML d’une page ne contiennent pas l’attribut type="module". Dans ce cas, l’erreur se produit parce que le JavaScript exécuté sur le web n’inclut pas la prise en charge par défaut de la syntaxe du module ES. Pour le code JavaScript envoyé par câble, vous pouvez rencontrer une erreur de partage de ressources inter-origines lorsque vous tentez de charger un module ES provenant d’un domaine différent.

Solution

Pour éviter l’erreur de module dans un navigateur plus ancien, assurez-vous que vous utilisez l’attribut de balise script correct – type="module" – dans le fichier HTML racine. Vous pouvez également utiliser Webpack pour transpiler le code afin que les navigateurs plus anciens puissent le comprendre.

Pour utiliser l’attribut type="module", incluez la ligne suivante dans votre fichier HTML racine :

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

Il est également essentiel de s’assurer que les chemins d’accès aux fichiers import sont valides et que vous utilisez la syntaxe import correcte.

En outre, vous pouvez consulter des sites tels que Can I Use pour vérifier la compatibilité des navigateurs avec les modules ES.

Enfin, étant donné que l’utilisation de l’extension de fichier .js est une pratique courante, vous pouvez définir l’attribut type dans la balise script du fichier HTML du module comme solution de contournement. En attribuant la valeur module à cet attribut, vous indiquez au navigateur de ne pas tenir compte de l’extension .js et de traiter le fichier comme un module.

Résumé

L’erreur « Cannot use import statement outside a module » peut apparaître pour diverses raisons, selon que vous vous trouvez dans un environnement JavaScript côté navigateur ou côté serveur. Une syntaxe incorrecte, des configurations inadéquates et des extensions de fichiers non prises en charge sont quelques-unes des sources les plus courantes de cette erreur.

Bien que la plupart des navigateurs modernes prennent en charge les modules ES, vous devez vous assurer que les navigateurs plus anciens sont compatibles. Les bundlers comme Webpack vous permettent de compiler tout le code source avec ses dépendances en une sortie unique que les navigateurs plus anciens peuvent comprendre.

N’oubliez pas d’ajouter l’attribut type="module" dans le fichier HTML pour informer le navigateur que le module est un module ES. Enfin, bien que l’utilisation de l’extension .js pour CommonJS soit la pratique par défaut, vous pouvez utiliser l’extension .mjs pour permettre l’importation de modules ES.

Vous avez une application JavaScript à mettre en ligne, mais vous ne voulez pas gérer les serveurs vous-même ? Les plateformes d’hébergement d’applications et de bases de données de Kinsta pourraient être la solution. Vous pouvez même combiner ces services avec l’hébergement de sites statiques de Kinsta pour que la partie frontend de votre application soit servie gratuitement.