NPMスクリプトの概要

NPMスクリプトは、NPMの私のお気に入りの機能の1つです。それらは単純です。それらはツールの必要性を減らします。したがって、構成ファイルやその他の追跡が必要なものの数が減ります。そして、それらは非常に用途が広いです。また、多くの一般的なタスクを自動化することもできます。そのうちのいくつかは記事の終わりにリストされています。

さらに面倒なことはせずに、NPMスクリプトに飛び込みましょう!

NPMスクリプトとは何ですか?

NPMスクリプトは、まあ、スクリプトです。スクリプトを使用して、反復的なタスクを自動化します。たとえば、プロジェクトを構築し、カスケードスタイルシート(CSS)ファイルとJavaScript(JS)ファイルを縮小します。スクリプトは、一時ファイルやフォルダなどの削除にも使用されます。これを実現する方法はたくさんあります。bash/ batchスクリプトを記述したり、GulpやGruntなどのタスクランナーを使用したりできます。ただし、多くの人がその単純さと汎用性のためにNPMスクリプトに移行しています。また、学習、使用、追跡するツールが少なくなる可能性もあります。

NPMスクリプトとは何か、そしてそれらが私たちのために何ができるかについての(いくつかの)アイデアが得られたので、先に進んでいくつかを書いてみましょう!

package.jsonのスクリプトオブジェクト

私たちの作業のほとんどは、NPMが一種のマニフェストとして使用するpackage.jsonファイルで行われます。これは、実行時に作成されるファイルです。npm init.

以下にサンプルのpackage.jsonファイルを示します。

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

NodeJSとNPMを使用している場合は、package.jsonファイルに精通しているはずです。scriptsファイル内のオブジェクトに注目してください。これがNPMスクリプトの行き先です。NPMスクリプトは、通常のJSONキーと値のペアとして記述されます。キーはスクリプトの名前であり、値には実行するスクリプトが含まれます。

これはおそらく最も人気のあるNPMスクリプトです(そしてそれは特別な種類のスクリプトでもあります):

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

あなたはおそらくあなたのpackage.jsonファイルでこれを何度も見たことがあるでしょう。そして、あなたはおそらくあなたがnpm startスクリプトを実行するためにタイプすることができることを知っています。ただし、この例は、NPMスクリプトの最初の重要な側面を示しています。これらは単なるターミナルコマンドです。それらは、実行されるOSのシェルで実行されます。したがって、Linuxの場合はbash、Windowsの場合はcmd.exeである可能性があります。

この時点で、あなたはかなり感銘を受けていないかもしれません。しかし、読み続けて、NPMスクリプトが実際にどれほど強力であるかを確認してください。

カスタムスクリプト

今見たスクリプトは、「特別な」NPMスクリプトの1つです。を入力するだけで実行できますnpm start。これらは、NPMが認識し、特別な意味を付加する名前のスクリプトです。たとえば、というスクリプトを作成できますprepublish。NPMは、パッケージがパックされて公開される前、およびnpm install引数なしでローカルで実行されるときにスクリプトを実行します。このようなスクリプトの詳細については、こちらをご覧ください。

ただし、NPMでは独自のカスタムスクリプトを定義することもできます。ここから、NPMスクリプトの力が発揮され始めます。

「helloworld」をコンソールに出力する非常に基本的なカスタムNPMスクリプトを見てみましょう。これをpackage.jsonファイルのscriptsオブジェクトに追加します。

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

package.jsonファイルのscriptsオブジェクトは次のようになります。

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

今すぐ実行してみてくださいnpm say-hello。動作しませんか?これは、カスタムNPMスクリプトの前に、run-scriptまたはrunそれらを正しく実行する必要があるためです。npm run-script say-helloまたはを実行してみてくださいnpm run say-hello。コンソールに「HelloWorld!」と表示されます。最初のNPMスクリプトを作成しました。

ここに簡単なヒントがあります—スクリプトの実行時にデフォルトのNPMログがコンソールに出力されないようにするには、--silentフラグを追加します。コマンドは次のようになります。

npm run --silent say-hello

他のNPMスクリプト内でのNPMスクリプトの呼び出し

NPMスクリプトを使用することの1つの欠点は、スクリプトがかなり複雑な(そして長い)場合に現れます。この問題は、JSON仕様がコメントをサポートしていないという事実によって悪化します。この問題を回避する方法はいくつかあります。1つの方法は、スクリプトを小さな単一目的のスクリプトに分割してから、他のNPMスクリプト内で呼び出すことです。別のスクリプト内でNPMスクリプトを呼び出す方法は簡単です。scripts次のようにオブジェクトを変更します。

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

NPMスクリプトはシェルで実行されるため、npm run say-hello別のNPMスクリプト内での呼び出しはほとんど直感的です。

ターミナルコマンドにあまり慣れていない人のため&&に、スクリプト内のを使用して2つのコマンドを区切ります。したがって、2番目のコマンドは、最初のコマンドが正常に実行された後に実行されます。

を実行するnpm run awesome-npmと、say-helloスクリプトが最初に実行され、コンソールに「Hello World」が出力され、その後に&&「NPM isawesome!」が出力されるスクリプトの一部が続きます。

これが役立つ可能性のあるユースケースを次に示します。アプリケーションのビルドプロセスを自動化しているとします。Webpackをバンドラーとして使用していて、配布コードが「dist」というディレクトリにあるとします。

あなたはディレクトリを掃除することから始めるかもしれません。これは、その内容を削除するか、ディレクトリ自体を削除してから再度作成することで実行できます。後者のアプローチで行きましょう。コマンドは次のようになります。

rm -r dist && mkdir dist
これはbashコマンドを使用することに注意してください。この記事の後半で、クロスプラットフォームのNPMスクリプトを作成する方法を学習します。

この後、webpackコマンドを実行してバンドラーを呼び出すことができます。

You can execute these commands in succession by using the &&operator. However, for the sake of demonstration and modularity, let’s split this into two NPM scripts that call each other.

Here’s what the scripts object would look like in this use case:

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

There you have it! How to split a more complex task into smaller NPM scripts.

Calling Shell and Node Scripts

At times, you may have to write scripts far more complex than ones that can be achieved in 2–3 commands. When this situation arises, one solution is to write bash or JS scripts (or scripts in any scripting language you like) and call them from NPM scripts.

Let’s quickly write a bash script that says hello to you. Create a file called hello.sh in your root directory and paste this code in it:

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

それはあなたの名前をあなたにエコーバックする単純なスクリプトです。次にpackage.jsonscriptsオブジェクトが次のコード行を持つようにファイルを変更します。

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

さて、あなたが走るとnpm run bash-hello、それはあなたにあなたの名前を尋ね、そしてあなたに挨拶します!鮮やかさ。

ノードを使用して実行されるJSスクリプトでも同じことができます。このアプローチの利点は、ノードを使用して実行するため、このスクリプトがプラットフォームに依存しないことです。コマンドライン引数として受け取った2つの整数を追加するためのもう少し複雑なJSスクリプトを次に示します(これを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]));}
process.argvオブジェクトには、スクリプトに指定されたコマンドライン引数が含まれています。最初の2つの要素process.argv[0]とはprocess.argv[1]、ノードによって予約されています。このようにprocess.argv[2]してprocess.argv[3]コマンドライン引数にアクセスしてみましょう。

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. ShellJSを使用する: ShellJSは、Nodeを介してUnixコマンドを実行するnpmパッケージです。したがって、これにより、Windowsを含むすべてのプラットフォームでUnixコマンドを実行できるようになります。
上記のアプローチは、CoryHouseがNPMスクリプトのためにGruntとGulpを離れた理由についてのこの素晴らしい記事から引用したものです。この記事では、このシリーズで取り上げられていない多くのことを詳しく説明し、優れたリソースのリストで締めくくっています。NPMスクリプトの理解を深めるために、これを読むことを強くお勧めします。

NPMスクリプトのいくつかのユースケース

最後に、NPMスクリプトでできることはたくさんあります。いくつかのユースケースは次のとおりです。

  • CSS / JavaScriptの縮小化/縮小化
  • ビルドプロセスの自動化
  • コードのリンティング
  • 画像の圧縮
  • 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! :)