Introduction aux scripts NPM

Les scripts NPM font partie de mes fonctionnalités préférées de NPM. Ils sont simples. Ils réduisent le besoin d'outils. Par conséquent, ils réduisent le nombre de fichiers de configuration et d'autres éléments dont vous avez besoin pour suivre. Et ils sont très polyvalents. Ils vous permettent également d'automatiser de nombreuses tâches courantes. dont certains sont répertoriés vers la fin de l'article.

Sans plus tarder, plongeons dans les scripts NPM!

Que sont les scripts NPM?

Les scripts NPM sont, bien, des scripts. Nous utilisons des scripts pour automatiser les tâches répétitives. Par exemple, créer votre projet, minimiser les feuilles de style en cascade (CSS) et les fichiers JavaScript (JS). Les scripts sont également utilisés pour supprimer des fichiers et des dossiers temporaires, etc. Il existe de nombreuses façons de réussir - vous pouvez écrire des scripts bash / batch, ou utiliser un exécuteur de tâches comme Gulp ou Grunt. Cependant, beaucoup de gens se tournent vers les scripts NPM pour leur simplicité et leur polyvalence. Ils offrent également la possibilité d'avoir moins d'outils à apprendre, à utiliser et à suivre.

Maintenant que nous avons (une certaine) idée de ce que sont les scripts NPM et de ce qu'ils peuvent faire pour nous, allons-y et écrivons-en quelques-uns!

L'objet Scripts dans package.json

La plupart de notre travail se déroulera dans le fichier package.json que NPM utilise comme un manifeste. C'est le fichier qui est créé lorsque vous exécuteznpm init.

Voici un exemple de fichier package.json:

{ "name": "super-cool-package", "version": "1.0.0", "scripts": { ... }, "dependencies": { ... } "devDependencies": { ... } }

Si vous avez travaillé avec NodeJS et NPM, vous serez familiarisé avec le fichier package.json. Notez l' scriptsobjet dans le fichier. C'est là que nos scripts NPM iront. Les scripts NPM sont écrits comme des paires clé-valeur JSON habituelles où la clé est le nom du script et la valeur contient le script que vous souhaitez exécuter.

Voici peut-être le script NPM le plus populaire (et c'est aussi un type de script spécial):

"scripts": { "start": "node index.js", ...}

Vous avez probablement vu cela des tonnes de fois dans vos fichiers package.json. Et vous savez probablement que vous pouvez taper npm startpour exécuter le script. Mais cet exemple illustre le premier aspect important des scripts NPM - ce sont simplement des commandes de terminal. Ils fonctionnent dans le shell du système d'exploitation sur lequel ils sont exécutés. Cela pourrait donc être bash pour Linux et cmd.exe pour Windows.

À ce stade, vous pourriez être plutôt peu impressionné. Mais continuez à lire pour voir à quel point les scripts NPM sont vraiment puissants.

Scripts personnalisés

Le script que nous venons de voir est l'un des scripts NPM «spéciaux». Vous pouvez l'exécuter en tapant simplement npm start. Ce sont des scripts avec des noms que NPM reconnaît et auxquels une signification particulière est attachée. Par exemple, vous pouvez écrire un script appelé prepublish. NPM exécutera le script avant que votre package ne soit compressé et publié, ainsi que lorsque vous exécutez npm installlocalement sans aucun argument. Plus d'informations sur ces scripts ici.

Mais NPM vous permet également de définir vos propres scripts personnalisés. C'est là que la puissance des scripts NPM commence à se manifester.

Examinons un script NPM personnalisé super basique qui affiche «hello world» sur la console. Ajoutez ceci à l'objet scripts de votre fichier package.json:

"say-hello": "echo 'Hello World'"

L'objet scripts dans votre fichier package.json doit ressembler à ceci:

..."scripts": { "start": "node index.js", "say-hello": "echo 'Hello World!'"}

Maintenant, essayez de courir npm say-hello. Ça ne marche pas? En effet, les scripts NPM personnalisés doivent être précédés de l'un run-scriptou l' autre ou runpour qu'ils soient exécutés correctement. Essayez d'exécuter npm run-script say-helloou npm run say-hello. La console dit «Hello World!»! Nous avons écrit notre premier script NPM!

Voici un petit conseil: pour empêcher les journaux NPM par défaut de sortir sur la console lorsque vous exécutez un script, ajoutez l' --silentindicateur. Voici à quoi ressemblerait votre commande:

npm run --silent say-hello

Appel de scripts NPM dans d'autres scripts NPM

Un inconvénient de l'utilisation de scripts NPM apparaît lorsque votre script est assez complexe (et long). Ce problème est aggravé par le fait que la spécification JSON ne prend pas en charge les commentaires. Il existe plusieurs façons de contourner ce problème. Une façon consiste à diviser votre script en petits scripts à usage unique, puis à les appeler dans d'autres scripts NPM. La manière d'appeler un script NPM dans un autre est simple. Modifiez votre scriptsobjet pour qu'il ressemble à ceci:

"scripts": { "say-hello": "echo 'Hello World'", "awesome-npm": "npm run say-hello && echo 'echo NPM is awesome!'"}

Étant donné que les scripts NPM s'exécutent dans le shell, l'appel npm run say-hellodans un autre script NPM est presque intuitif.

Pour ceux d'entre vous qui ne sont pas très à l'aise avec les commandes de terminal, le &&dans le script est utilisé pour délimiter deux commandes. Ainsi, la deuxième commande s'exécute après l'exécution réussie de la première commande.

Désormais, lorsque vous exécutez npm run awesome-npm, le script say-hello s'exécute en premier, générant «Hello World» sur la console, suivi de la partie du script après le &&, qui renvoie «NPM is awesome!»

Voici un cas d'utilisation où cela pourrait être utile. Supposons que vous automatisez le processus de création de votre application. Disons que vous utilisez Webpack comme bundler et que votre code de distribution entre dans un répertoire appelé «dist».

Vous pouvez commencer par nettoyer le répertoire. Cela peut être fait en supprimant son contenu ou en supprimant le répertoire lui-même puis en le reconstituant. Allons-y avec cette dernière approche. Votre commande pourrait ressembler à ceci:

rm -r dist && mkdir dist
Notez que cela utilise des commandes bash. Vous apprendrez à écrire des scripts NPM multiplateformes plus loin dans cet article.

Après cela, vous pouvez appeler le bundler en exécutant la webpackcommande.

Vous pouvez exécuter ces commandes successivement à l'aide de l' &&opérateur. Cependant, dans un souci de démonstration et de modularité, divisons cela en deux scripts NPM qui s'appellent.

Voici à quoi ressemblerait l'objet scripts dans ce cas d'utilisation:

"scripts": { ... "clean": "rm -r dist && mkdir dist", "build": "npm run clean && webpack"}

Voilà! Comment diviser une tâche plus complexe en scripts NPM plus petits.

Appel de scripts Shell et Node

Parfois, vous devrez peut-être écrire des scripts beaucoup plus complexes que ceux qui peuvent être réalisés en 2–3 commandes. Lorsque cette situation se présente, une solution consiste à écrire des scripts bash ou JS (ou des scripts dans n'importe quel langage de script de votre choix) et à les appeler à partir de scripts NPM.

Écrivons rapidement un script bash qui vous dit bonjour. Créez un fichier appelé hello.shdans votre répertoire racine et collez-y ce code:

#!/usr/bin/env bash
# filename: hello.shecho "What's your name?"read nameecho "Hello there, $name!"

C'est un script simple qui vous renvoie votre nom. Modifiez maintenant le package.jsonfichier pour que l' scriptsobjet ait cette ligne de code:

"bash-hello": "bash hello.sh"

Maintenant, quand vous courez npm run bash-hello, il vous demande votre nom et vous dit bonjour! Brillant.

Vous pouvez faire la même chose avec les scripts JS exécutés à l'aide de node. Un avantage de cette approche est que ce script sera indépendant de la plate-forme car il utilise node pour s'exécuter. Voici un script JS légèrement plus complexe pour ajouter deux entiers reçus comme arguments de ligne de commande (placez-le dans un fichier nommé add.js):

// add.js// adds two integers received as command line arguments
function add(a, b) { return parseInt(a)+parseInt(b);}
if(!process.argv[2] || !process.argv[3]) { console.log('Insufficient number of arguments! Give two numbers please!');}
else { console.log('The sum of', process.argv[2], 'and', process.argv[3], 'is', add(process.argv[2], process.argv[3]));}
L'objet process.argv contient les arguments de ligne de commande donnés au script. Les deux premiers éléments, process.argv[0]et process.argv[1], sont réservés par nœud. Ainsi process.argv[2]et process.argv[3]vous permet d'accéder aux arguments de la ligne de commande.

Now add this line to the scripts object of the package.json file:

"js-add": "node add.js"

Finally, run the script as an npm script by giving it two numbers as command line arguments:

npm run js-add 2 3

And viola! The output is

The sum of 2 and 3 is 5

Brilliant! Now we’re capable of writing much more powerful scripts and leveraging the power of other scripting languages.

Pre and Post Hooks

Remember how we talked about a special npm script called prepublish that runs before you publish your package? Such a functionality can be achieved with custom scripts too. We’ve discussed one way to do this in the previous section. We can chain commands using the &&operator, so if you wanted to run script-1 before script-2, you would write:

"script-2": "npm run script-1 && echo 'I am script-2'"

However, this makes our scripts a little dirty. This is because the core functionality of the script is reflected only in the second part of the command (after the && ). One way to write clean scripts is to use pre and post hooks.

Pre and post hooks are exactly what they sound like — they let you execute scripts before and after you call a particular script. All you have to do is define new scripts with the same name as your main script. Yet these are prefixed with “pre” or “post” depending on whether the script is executed before the main script or after it.

Let’s look at our say-hello script again. Say we want to execute the command echo 'I run before say-hello' before say-hello and echo 'I run after say-hello' after say-hello. This is what your scripts object would look like:

"scripts": { "say-hello": "echo 'Hello World'", "presay-hello": "echo 'I run before say-hello'", "postsay-hello": "echo 'I run after say-hello'" }

The “pre” and “post” before the script names tell npm to execute these before and after the script called say-hello respectively.

Now, when you run npm run say-hello, the output of all three scripts shows up in order! How cool is that?

Since all three scripts output to the console and the NPM logs clutter the output, I prefer using the -silent flag while running these. So your command would look like this:

npm run --silent say-hello

And here’s the output:

I run before say-helloHello WorldI run after say-hello

There you have it!

Let’s apply this knowledge to our build script example. Modify your package.json file so that it looks like this:

"scripts": { ... "clean": "rm -r dist && mkdir dist", "prebuild": "npm run clean" "build": "webpack"}

Now our scripts look much cleaner. When you run npm run build, prebuildis called because of the “pre” hook, which calls clean, which cleans up our dist directory for us. Sweet!

Making Our Scripts Cross-Platform

There is one drawback of writing terminal/shell commands in our scripts. This is the fact that shell commands make our scripts platform dependently. This is perhaps what draws our attention to tools like Gulp and Grunt. If your script is written for Unix systems, chances are, it won’t work on Windows, and vice versa.

The first time I used NPM scripts, which called other bash/batch scripts, I thought of writing two scripts per task. One for Unix and one for the Windows command line. This approach may work in use cases where the scripts aren’t that complex and there aren’t many scripts. However, it quickly becomes clear that they are not a good solution to the problem. Some of the reasons behind this are:

  • You have another thing to keep track of that distracts you from your primary task of working on the application. Instead, you end up working in the development environment.
  • You’re writing redundant code — the scripts you write are very similar and accomplish the same task. You’re essentially rewriting code. This violates one of the fundamental principles of coding — DRY: Don’t Repeat Yourself.

So how do we get around this? There are three approaches that you may use:

  1. Use commands that run cross-platform: Many useful commands are common to Unix and Windows. If your scripts are simple, consider using those.
  2. Use node packages: You can use node packages like rimraf or cross-env instead of shell commands. And obviously, you can use these packages in JS files if your script is large and complex.
  3. Utilisez ShellJS: ShellJS est un package npm qui exécute des commandes Unix via Node. Cela vous donne donc le pouvoir d'exécuter des commandes Unix sur toutes les plates-formes, y compris Windows.
Les approches ci-dessus sont tirées de cet article brillant de Cory House expliquant pourquoi il a quitté Grunt et Gulp pour les scripts NPM. L'article détaille de nombreuses choses non couvertes dans cette série et se termine par une liste d'excellentes ressources. Je vous recommande vivement de le lire pour approfondir votre compréhension des scripts NPM.

Quelques cas d'utilisation des scripts NPM

Enfin, vous pouvez faire beaucoup avec les scripts NPM. Certains cas d'utilisation sont:

  • Minification / Uglification de CSS / JavaScript
  • Automatiser le processus de construction
  • Linting votre code
  • Compression d'images
  • Injection automatique des modifications avec BrowserSync

And a lot more. To learn about how to automate the above-mentioned tasks using NPM scripts, check out this brilliant article on the topic.

Bonus: Commander for Creating CLI Applications Using NodeJS

While we’re discussing NPM scripts and the CLI, I’d like to quickly tell you about a really cool package called commander. Commander allows you to create your own CLI applications. This isn’t really related to NPM scripts, but it’s a cool piece of technology to know. Check out the commander docs here or try one of these tutorials:

  • Build An Interactive Command-Line Application with Node.js — Scotch.io
  • Writing Command Line Applications in NodeJS — freeCodeCamp

Concluding Words

That is all for this article on using NPM scripts. I hope you’ve gained some insight on how you can integrate these into your own projects. This article is by no means an in-depth tutorial on NPM scripts. Hence I’d recommend you learn further both from other resources and from actually using NPM scripts in your own projects.

Also, do connect with me on GitHub and LinkedIn.

Happy Coding! :)