Inclure un fichier JavaScript dans un autre avec Node.js

Sans le transformer en module, on peut aussi inclure un fichier dans un autre grâce aux fonctions de Node.

En ligne de commande, l'interpréteur JavaScript ne peut par lui-même inclure de fichier dans le fichier qu'il interprête, puisqu'il est conçu pour traiter des fichiers déjà chargés en mémoire, par le navigateur. Mais en utilisant le module vm de node pour charger le fichier on se substitue au navigateur. Vm est un module de base que l'on n'a pas besoin d'installer.

A titre d'exemple, on veut charger le fichier extfile.js qui a le contenu suivant:

// JavaScript Document

var extvar = "hello externe"

function extfun(a, b) {
var c = a * b
return c
}

Dans le fichier principal on importe les modules fs et vm, et on ajoute une fonction de chargement:

// JavaScript Document

var fs = require("fs")
var vm = require('vm')

var content = fs.readFileSync(filename)
vm.runInThisContext(content)

On peut réduire le chargement à une seule instruction:

vm.runInThisContext(fs.readFileSync(__dirname + "/extfile.js"))

Laquelle instruction est équivalente à la fonction include de PHP ou la directive #include de C.

On peut alors dans le premier fichier JavaScript utiliser directement les variables et fonctions que le ou les fichiers inclus contiennent:

console.log(extvar)
console.log(extfun(10, 50))

Ce qui affiche 'hello externe' puis '500'.

Le code de la démo est fourni dans l'archive à télécharger.

Cette méthode a deux inconvénients:

  1. Le fichier inclut n'a pas accès aux variables déclarées dans le fichier principal.
  2. On ne peut utiliser la fonction require dans le fichier inclut parceque vm fait appel à V8 et donc ignore les fonctions de Node.
  3. Donc on ne peut utiliser la bibliothèque standard dans le fichier inclut.

Pour avoir accès au contexte global, y compris aux objets assignés par require on utilisera plutôt la fonction eval:

eval(fs.readFileSync(__dirname + '/extfile.js')+'');

Qui supprime toutes les limitations précédentes. Ajouter une chaîne vide à la fin du code chargé par readFileSync est indispensable.

Utiliser le navigateur

La méthode précédente est indispensable si on veut pouvoir interagir avec le programme en ligne de commande (en utilisant fs.readSync pour entrer des données).

Si on se contente d'afficher les résultats d'un programme, on peut aussi se passer du module de chargement en utilisant le navigateur et en générant les résultats dans une page Web. Le code du fichier principal se présentera alors ainsi :

<script src="extfile.js"></script>
<script>
document.write(extvar)
document.write("<br>")
document.write(extfun(10, 50))
document.write("<br>")
</script>

Le fichier à inclure est inchangé, sauf s'il contient des instructions d'affichage.

Cette seconde méthode est sans doute plus efficace que l'utilisation du module vm ou de eval mais oblige à remplacer console.log par document.write.

Fichier à inclure fréquemment

Finalement, quand le module à inclure est destiné à être souvent réutilisé, le transformer en module est la solution optimale. Les attributs et méthodes deviennent exportables:

exports.extvar = "hello externe"
exports.ext = functionf(a, b) {
var c = a * b
return c
}

Il faudra ajouter le nom du module en préfixe pour utiliser son contenu:

var extfile = require("extfile.js")
console.log(extfile.extvar)
console.log(extfile.extfun(10, 50))

En conclusion, on a le choix entre quatre solutions pour inclure un fichier externe, chacune convenant mieux à chaque situation particulière.

Télécharger le code des exemples.

Le fichier demovm.js est le premier exemple avec résultats en fenêtre de commande et demohtml.html le second avec les résultats dans un fichier HTML.