CJS versus ESM

 

Extension .mjs

Dans la version 20 de la documentation de node 20.x, je vois apparaître deux types d'importation possibles !

📥ESM

📥CJS

Nous allons tenter de comprendre comment gérer ces deux options !

🪛Mise en place

Créez un fichier  util.js 

utils.js 

  1. export const getFullName = (firstname, lastName) => {

  2.   return `my fullname is ${firstname} ${lastName}`;

  3. };


  4. const fullname = getFullName("Dupont", "Denis");


Créez un fichier  app.js 

app.js 

  1. import { getFullName } from "./util.js";

  2. const fullName = getFullName("dupont", "denis");


Dans un terminal exécuter la commande >node app.js

La figure suivante, nous signale un problème 

L'importation échoue ! Nous allons expliciter le Warning affiché.

Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.


1️⃣Use .mjs extension

Vous l'aurez compris :  une "nouvelle" extension existe.

🥷mjs (m = module)


Pour corriger très rapidement les extensions, nous utilisons les facilités de VScode.

Il nous suffit de renommer les noms de fichiers. Il vous suffit de faire un clic droit sur le nom du fichier et de choisir l'option Rename… F2


JS

Module JS

app.js

app.mjs

utils.js

utils.mjs


Lorsque nous modifions le nom de utils.js en utils.mjs, VS Code peut mettre à jour les importations.

Cliquez sur le bouton par défaut. Vérifiez alors que dans le fichier, le nom du module change.

Il faut enregistrer les modifications dans le fichier app.mjs.



2️⃣set "type": "module" in the package.json

Revenons à la situation de départ. Nous disposons de deux fichiers JS.

Pour gérer une application, il nous faut initialiser un fichier package.json.

TD node : npm 1

Pour créer le fichier package.json, nous facilite la tâche. 

En effet, npm monte la structure. 


Dans le terminal taper la commande : npm init -y 

$ npm init -y


🪛Dans le fichier package.json ajouter la ligne "type":"module",

🪛Vérifiez que la commande node app.js s'exécute sans warning.


🆘En action

Nous allons tenter d'exécuter l'exemple de la document 20.x

Vous créez un📁répertoire tmp et créer un fichier hello.txt.

Créer un fichier app.js à la racine. Recopiez le code de l'exemple.

app.js 

  1. import { unlink } from "node:fs/promises";


  2. try {

  3.   await unlink("/tmp/hello");

  4.   console.log("successfully deleted /tmp/hello");

  5. } catch (error) {

  6.   console.error("there was an error:", error.message);

  7. }


Modifiez le code des lig. 4-5. Pour rechercher le fichier à la racine du répertoire courant et non vers 'C:\tmp\hello.txt'

  1.   await unlink("./tmp/hello.txt");

  2.   console.log("successfully deleted ./tmp/hello.txt");



Si on exécute node app.js, nous obtenons les warning expliqués dans le cours.

>node app.js


Renommer le fichier app.js en app.mjs et lancez le code

>node app.mjs

successfully deleted ./tmp/hello.txt

et relancez le code

>node app.mjs

there was an error: ENOENT: no such file or directory, unlink 'C:\Users\DD\Desktop\testModules\tmp\hello.txt'

Revenons à la situation de départ avec notre fichier app.js, et créons un fichier package.json.

Dans le terminal taper la commande : npm init -y 

$ npm init -y

🪛Dans le fichier package.json ajouter la ligne "type":"module",

Lancez le code

>node app.js

successfully deleted ./tmp/hello.txt


🆘En action

Nous allons tenter d'exécuter l'exemple de la document 20.x

Vous créez un📁répertoire tmp et créer un fichier hello.txt.

Créer un fichier app.js à la racine. Recopiez le code de l'exemple.

app.js 

  1. const { unlink } = require('node:fs/promises');


  2. (async function(path) {

  3.   try {

  4.     await unlink(path);

  5.     console.log(`successfully deleted ${path}`);

  6.   } catch (error) {

  7.     console.error('there was an error:', error.message);

  8.   }

  9. })('/tmp/hello');

Modifiez le code de la ligne 10. Pour rechercher le fichier à la racine du répertoire courant et non vers 'C:\tmp\hello.txt'

  1.   })("./tmp/hello.txt");


Lancez le code

>node app.js

successfully deleted ./tmp/hello.txt


Le code app.js peut être compris comme étant équivalent à l'exécution immédiate d'une fonction anonyme. Voici une réécriture avec une déclaration explicite d'une fonction run.

 

app.js 

  1. const { unlink } = require("node:fs/promises");


  2. const run = async function (path) {

  3.   try {

  4.     await unlink(path);

  5.     console.log(`successfully deleted ${path}`);

  6.   } catch (error) {

  7.     console.error("there was an error:", error.message);

  8.   }

  9. };


  10. run("./tmp/hello.txt");



Annexe

https://nodejs.org/docs/latest-v13.x/api/esm.html#esm_enabling