Mixer les ESmodules et les modules CommonJS dans un projet NodeJS

NodeJs est apparu avec les commonJs modules, puis après avec la grosse évolution de ES, qui a introduit les ES Module, est apparu une seconde façon de faire plus moderne. A quoi ressemble un module CommonJS?

Du point de vue d’un script NodeJS la syntaxe est la suivante

const express = require('express')

La syntaxe ES Module utilise le mot clé import

import Express from 'express'

Je rappelle qu’un module est un script Javascript. Dans le fichier package.json, il y a un champ qui dit quel système de module utiliser

{
  "name": "cloneflicker",
  "private": true,
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
    "lint": "eslint -c 'eslint.config.js' src"
  },
....

Dans le script ci-dessus, type est associé à « module », alors que cela pourrait être « commonjs ».

En mode « commonjs », les fichier avec extension .cjs,.js sont traités comme module CommonJS, mais voyons cela dans un tableau récaitulatif

Extension de fichiersComportement en type= »commonjs »Comportement en type= »module »
.cjsCommonJS moduleCommonJS module
.jsCommonJS moduleES Module
.mjsES ModuleES Module

On voit dans ce tableau que les extensions cjs et mjs sont invariable, et que c’est js qui peut changer de comportement suivant le contexte.

Règles d’application

Dans le contexte ES Module:

on import ou export dans ce contexte

//  salutation.js
export function saluer(){
    console.log("Bonjour !")
}



puis plus tard en utilisation dans un autre fichier index.js

import saluer from './salutation.js'

Dans le contexte CommonJS:

//  salutation.js

function saluer(){
    console.log("Bonjour !")
}

module.exports = saluer

puis plus tard en utilisation dans un autre fichier index.js

const saluer = require('./salutation.js')

Vous ne pouvez utiliser que import et export dans un ES Module, c’est à dire lorsque vous êtes dans un fichier mjs ou js avec type : « module » (Cannot use import statement outside a module, Unexpected token ‘export’)

Vous ne pouvez pas utiliser require dans un ES Module, vous devez utiliser import (ReferenceError: require is not defined)

Vous ne pouvez utiliser require pour charger un EX Module (Error [ERR_REQUIRE_ESM]: Must use import to load ES Module

Cela semble logique, quand on sait dans quel contexte on est, on joue avec les règles. Ainsi On ne peut mélanger les syntaxe des 2 contexte. MAIS il y a un cas où l’on peut mélanger (quoique je ne vous recommande pas d’utiliser expliciter, mais lorque vous êtes obligé seulement)

Un ES Module peut importer un module exporté depuis un contexte CommonJS

Je vous donne ct exemple tiré de cet article :

https://pencilflip.medium.com/using-es-modules-with-commonjs-modules-in-node-js-1015786dab03

// module1.js
console.log("require module1");
import obj from "./module2.cjs";
console.log(`module2 = ${obj.module2}`);
// module2.cjs
console.log("require module2");
exports.module2 = "require module2";
Retour en haut