新しいことにはウェルカム

技術 | 電子工作 | ガジェット | ゲーム のメモ書き

Node.jsを初めて学ぶにあたってハマったことや勘違いしていたことなど

Node.jsを使っているのですが、Node.jsを学ぶ前と後では、Node.jsに対する印象が結構違ったので、Node.jsの簡単な説明と、学ぶにあたって個人的にはまったところを簡単にまとめました。

Node.jsとは

Node.jsとは、JavaScriptの実行環境のことです。

JavaScriptというと一般的にブラウザー上で動かすものですが、Node.jsをインストールすると、ブラウザとは関係なく、JavaScript単体でプログラムを動かすことができるようになります。

ChromeのJavaScript実行エンジンはオープンソースで公開されており、そのJavaScript実行エンジンを取り出して、JavaScript単体で動くようにさせたのがNode.jsです。

PCローカルファイルの読み書き等、ブラウザ内で動かしたJavaScriptではできない、ブラウザ外のOS機能へのアクセスが可能になっていて、PC上で動かす言語の一つとしてJavaScriptが使えるようになっています。

例えば、phpをインストールしているPCでは、phpのプログラムは$ php test.phpと打てば実行できるように、Node.jsをインストールしているPCでは、JavaScriptのプログラムは$ node test.jsと打つと実行されます。

test.js

console.log('Hello World!');

Node.jsはどんな所で使われているのか?

Node.jsは主に

  • ウェブサーバーとしての利用
  • JavaScript開発環境としての利用

の用途において、利用されることが多いです。

ウェブサーバーとしての利用

例えば、ウェブサイトでphpが動く流れはこんな感じです。

  1. ユーザーが、ウェブサイトにアクセスする
  2. Nginx・Apache等のウェブサーバーが、アクセスを受ける
  3. ウェブサーバーが、アクセスしてきたURLを見て、どのphpプログラムを実行するかを決める
  4. ウェブサーバーが、phpを起動して上記のphpプログラムを実行させる

一方Node.jsの場合、ウェブサーバー自体をJavaScriptプログラムとして作成し、Node.jsで実行します。

例えば、http://localhost:3000で「Hello World!」と表示するサーバープログラムは次のようになります。 プログラムを作成し、$ node test.jsとコマンドを打てば、Node.jsがウェブサーバーとなります。

const http = require('http');
const port = 3000;

const server = http.createServer((request, response)=>{
    response.end('Hello World!');
});

server.listen(port);

仕組み

最後のserver.listen(port)で、ポート3000番のアクセスをチェックし続ける永久ループが回っているため、プログラムは終了せず、ポートにアクセスがあれば「Hello World!」と応答するwebサーバーができあがります。

Node.jsはJavaScriptの実行環境に過ぎないので、「Node.js=ウェブサーバー」ではないのですが、ウェブサーバーとして利用されることが多いため、ここに記載しました。

もちろん、プログラムが永続しない、バッチ処理的な書き方も可能ですし、実際、そのような使われ方もよくされます。

どうしてサーバーで使う言語としてNode.jsが注目されているのか?

Node.jsは、ウェブサーバープログラムを含め、サーバーで動かすプログラムとして注目されることが多いです。

ウェブサービスを構築する際、沢山のアクセスがあった時にユーザーの待ち時間が増えないよう、サーバープログラムは、いかに沢山のアクセスがさばけるかが重要になってきます。

Node.jsは他の言語と比較して、沢山のアクセスに強いため、サーバーで動かす言語として使われることが多いのです。

仕組み

同じPCなのに、Node.jsでプログラムを書くとアクセスに強くなるのは何故でしょう。

それは、Node.jsが

  • 単一プログラム
  • 非同期処理

をベースとして動いているからです。

単一プログラム

一般的に、他のプログラム言語では、ユーザーからのアクセスがある度に、新しくプログラムが実行されます。

新しくプログラムが実行される度に、そのプログラム用にCPU・メモリが割り当てられられるので、同時アクセス数に比例してPCのCPU・メモリの使用量が増えていきます。

一方Node.jsでは、前述のウェブサーバープログラムのように、プログラムは最初に起動したものだけで、そのプログラムがユーザーからのアクセスを待ち受けて、ユーザーからのアクセスがあるとそのプログラムが処理します。

なので、同時アクセスユーザー数が増えても、CPU・メモリの使用量は比例しては増えず、多くのアクセスをさばけるのです。

非同期処理

Node.jsでは、ほとんどの関数が非同期で実行されます。

非同期関数とはザックリ言うと、何か関数を実行する時に、まず実行スタートだけ行い、実際の処理は、処理可能になったタイミングで、後から関数が呼び出されて実際の処理を行う関数の書き方のことです。

例えばウェブサイトにアクセスして情報を取得する関数があったとします。

他のプログラム言語の場合、関数を実行すると、サイトにアクセスして情報をゲットするまで関数は返ってきません。

なので、サイトのレスポンスが遅い場合、関数を実行すると、そこで長い間プログラムがロックされます。

一方Node.jsでは、関数を実行すると関数は、サイトの情報が取得されたら教えて欲しいという登録だけして終了し、次の処理に移ります。そして、情報をゲットし終わると関数が呼び出され、情報を取得した後の処理が実行されます。

プログラムにすると下記のようになります。

fetch('https://www.google.com')
    .then(res=>{
        return res.text();
    }).then(text=>{
        console.log(text);
    });

fetch('https://www.bing.com')
    .then(res=>{
        return res.text();
    }).then(text=>{
        console.log(text);
    });

fetch()はURLにアクセスして中身を取得する関数で、取得結果をconsole.log(text)で出力しています。

「google→bing」の順に出力されるかというとそうではなく、一番レスポンスが早かったものから出力されます。

つまり、Node.jsは、何かを待つということはせず、とりあえずやることは全てタスクリストに入れておき、そのタスクが実行可能になったものから実行していくというスタイルになります。

なので、待ち時間が無い分、時間あたりにできることが多くなり、多くのアクセスをさばけるのです。

JavaScript開発環境としての利用

Node.js登場以前のJavaScriptは、html・画像・cssといった、サイトのリソースの1つに過ぎませんでした。

しかしNode.jsの登場で、Web開発者にとって馴染みのあるJavaScriptでPCのプログラムが書けるようになったことにより、Webサイトの開発環境や、その他のアプリケーションやツールもJavaScriptで作られるようになってきました。

ブラウザで実行されるJavaScriptを書く場合でも、まずローカルのPCにNode.jsをインストールして、Node.jsで書かれたWebサイト作成に関する様々なツール・アプリを使って、サイトのJavaScriptを作成するケースが増えてきています。

つまり、当初はサーバーで使うためのプログラムが多かったのですが、今では、ローカルPCで使うアプリを動かす言語としての利用が増えてきました。

その他感想など

個人的には、非同期関数の書き方がとっつきにくく苦労しました。

同期関数のプログラムと違い、プログラムが上から順に実行されず、何がいつ起こるかを理解するには、ある程度Node.jsの内部構造を知らないといけないため、単に言語としてのJavaScriptの学習に加えて、Node.js・非同期関数の学習が必要になってきます。

また、同じことをするプログラムでも、非同期関数がゆえに、他のプログラム言語と比較して、書きづらく、読みづらいです。

例えば、1秒ずつ空けて「Hello」「World!」と表示するプログラムをPythonとJavaScriptで書くと次のようになります。

import time

time.sleep(1)
print('Hello')

time.sleep(1)
print('World!')
setTimeout(()=>{
    console.log('Hello');

    setTimeout(()=>{
        console.log('World!');

    , 1000);
, 1000);

しかし、Node.js(JavaScript)を使うメリットも大きいので学ぶ価値はあるかと思います。

  • 動作が軽い(沢山のアクセスに強いという点で)
  • 応用範囲が広い
    • ブラウザ・サーバー・ローカルプログラム全てが書ける
    • 大抵のライブラリはそろっていて、事例が多い(何でもできて、そのための情報も多い)

まとめ

  • JavaScriptを言語単体で動くようにしたものだよ。ブラウザとは関係ないよ
  • 沢山のアクセスに強いよ。なので、ウェブサービス・サーバーサイド向きの言語だよ
  • サーバーサイド以外でも普通のプログラム言語として使えるよ。むしろ、サーバー以外の使われ方の方が増えてきているよ
  • プログラムの書き方が、他のプログラム言語から見るととっつきにくいよ