フロントエンドからフルスタックまで前編
Node.jsとは
Node.js は、2009年初に Ryan Dahl によって Chrome V8 エンジンを基に開発された JavaScript ランタイム環境です。
そのため、Node.js も JavaScript のホスト環境の一種です。
その下層は、私たちがよく知っている Chrome ブラウザの JavaScript エンジンであるため、実質的には Chrome ブラウザで動作する JavaScript とは何も異なりません。
しかし、Node.js のランタイム環境は、ブラウザのランタイム環境とはまだ異なります。
Node.js はブラウザではないので、Window オブジェクトや Location オブジェクト、Document オブジェクト、HTMLElement オブジェクト、Cookie オブジェクトなど、ブラウザが提供する DOM API を持っていません。
しかし、Node.js は独自の API を提供しています。例えば、グローバルの global オブジェクトや現在のプロセスの情報を提供する Process オブジェクト、ファイルを操作する fs モジュール、Web サーバを作成する http モジュールなどです。
これらの API を使用することで、JavaScript を使用してコンピュータを操作できるので、Web サーバを開発することができます。
また、Node.js とブラウザで共通するオブジェクトもあります。例えば、V8 エンジンが提供する JavaScript エンジンの内蔵オブジェクトです。
Node.js のベースアーキテクチャ
Node.js の基本的な構造は、上記の図で示されています。
そこでは、Node.js がオペレーティングシステムの上に実行されることがわかります。
その下層は、V8 JavaScript エンジンと、libUV ライブラリ、c-ares、llhttp/http-parser、open-ssl、zlibなどのいくつかのC/C++ライブラリで構成されています。その中で、libUVはイベントループを処理するためのものであり、c-ares、llhttp/http-parser、open-ssl、zlibのようなライブラリは、DNSの解決、HTTPプロトコル、HTTPS、およびファイルの圧縮などの機能を提供します。
これらのモジュールの上層には、中間層があり、その中間層にはNode.js Bindings、Node.js Standard Library、およびC/C++ AddOnsが含まれます。
Node.js Bindings層は、C/C++で書かれたライブラリのインターフェイスをJS環境に暴露することを目的としています。一方、Node.js Standard Libraryは、Node.js自体のコアモジュールです。
C/C++ AddOnsは、ユーザーが自分のC/C++モジュールをNode.jsに提供するために橋渡しを使用することができます。
中間層の上には、Node.jsのAPI層があります。Node.jsを使用してアプリケーションを開発するときは、主にNode.jsのAPI層を使用します。そのため、Node.jsのアプリケーションは最終的にNode.jsのAPI層上で実行されます。
Node.js は何ができるのですか?
Node.jsは操作システム上で動作するJavaScriptランタイム環境で、操作システムのAPIを提供しており、これらを使用することで、操作システムのコマンドを実行したり、ファイルを読み書きしたり、ネットワーク接続を作成したり、操作システム上の他のサービスを呼び出したりすることができます。
Node.jsよく使われる主要なものは以下のものです。
File Systemモジュール:これは、ディレクトリとファイルを操作する模块で、読み取り、書き込み、作成、削除、アクセス権の設定などを提供します。
Netモジュール:TCP接続を作成するためのソケットを提供します。
TCP接続は、バックエンドデータベースやその他の永続的なサービスにアクセスするために使用できます。
URLモジュール:クライアントリクエストのURL情報を処理する補助モジュールであり、URL文字列を解析することができます。
Pathモジュール:ファイルパス情報を処理する補助モジュールであり、ファイルパスの文字列を解析することができます。
Processモジュール:プロセス情報を取得するために使用されます。
Bufferモジュール:バイナリデータを処理するために使用されます。
consoleモジュール:コンソールモジュール、ブラウザのconsoleモジュールと同じで、コンソールに情報を出力するために使用されます。
Crypto暗号化解読モジュール:ユーザーの認可が必要なサービスを処理するために使用されます。
Eventsモジュール:ユーザーイベントを監視し、配信するために使用されます。
HTTP モジュール:HTTP 接続を作成する能力を提供し、Web サービスを作成できます。また、Node.js で最もよく使われるフロントエンドの核心モジュールです。
以上のモジュールは後続のコースですべて使用することになります。ここでは大まかな印象をつけるだけで十分です。さらに、Node.jsには他のモジュールもあり、興味のある方はNode.jsの公式ドキュメントでこれらのモジュールの紹介をご覧ください。
上記のコアモジュールのほかに、Node.jsのコミュニティ生態も非常に活発で、たくさんの第三者モジュールが使用できます。これらはすべてNPMパッケージ管理ツールを使用してインストールできます。後続のコースでもいくつか紹介する予定です。
とりあえず、今からNode.jsをシステムにインストールして、小さなサンプルを書いてNode.jsを使ってみましょう!
Node.js 公式サイト
Node.jsをダウンロードするには、nodejs.orgのオフィシャルサイトから、お使いのオペレーティングシステムに合わせたNode.jsをダウンロードできます。MacOS、Linuxシステム、X86や64ビットのWindowsシステムでも、それぞれに対応したバージョンがあります。
Node.js のインストール方法
ここで、2 つのバージョンがあります。
1 つは LTS 版 (Longterm Support 版、長期サポート版)、つまり、官方が推奨するより成熟して安定したバージョンである 16.16.0 です。
もう 1 つは Current 版 (現在のバージョン)、つまり、現在リリースされている最新バージョンであり、安定していませんが、最も多くの新しい機能が含まれています。
通常、オンライン Web アプリを開発する場合は、安定性を考慮して LTS 版を優先的に選択することが多いです。
このコースでは、このバージョンを選択します。
$ node -v v16.16.0
対応するバージョンをダウンロードして展開してインストールすることで、インストール完了後、コマンドラインターミナルを開き、コマンド node -v を実行すると現在インストールされている Node.js のバージョン番号を確認することができます。
NPMとは
NPM(Node Package Manager)は、Node.js パッケージを管理するためのツールです。Node.js にはたくさんの第三者のモジュールがあり、これらは NPM を使用してインストールできます。また、NPM も第三者のモジュールとして公開されており、それらを使用することで、Node.js のアプリケーションをより簡単に開発することができます。
Node.jsのモジュールは、基本的には内部モジュールとその他のモジュールに分かれます。
内部モジュールは、Node.jsがデフォルトで組み込んでいるモジュールで、importやrequireを使用してモジュール名を参照する必要はありません。
Node.jsには、モジュールの管理に関する情報を含む内部モジュール「module」が用意されています。
このモジュールを使用して、現在のNode.jsのバージョンで利用できるすべての内部モジュールを取得することができます。
show_builtins.jsというファイルを作成し、以下のコードを記述します。
// show_builtins.js
const {builtinModules} = require('module');
console.log(builtinModules);
そして、node show_builtins.jsを実行し、すべての内蔵モジュールの名前の情報を表示することができます:
Node.jsには、数十個の内置モジュールがあります。その中には、console、fs、httpなどの常用モジュールがあります。
これらは後続のコースで詳しく説明します。
ここでは、モジュール名を使用して、自分のモジュールにインポートすることができることを知っておけば十分です。
例えばfsモジュールは、ファイル操作に関連するモジュールです。下記のコードを使用することで、fsモジュールをインポートし、ファイルを操作することができます。
const fs = require('fs');
内置模块以外のモジュールは、2つの方法でインポートすることができます。
1つは、ファイルパスを使用してインポートする方法です。
例えば、Aが書いたfoo.jsがプロジェクトのaサブディレクトリにあり、Bが書いたbar.jsがbサブディレクトリにあるとします。BがAのfoo.jsをインポートしたい場合は、bar.jsファイルでパスを使用してロードする必要があります:
const bar = require('../a/foo.js');
もしプロジェクトが多くのモジュールを導入する必要がある場合、それらモジュールのディレクトリを手作業で管理することは大変で、ミスも起きやすい作業です。
また、Aさんが書いたファイルを多くの人がインターネット上から利用したい場合、人それぞれがそのファイルをダウンロードし、プロジェクトのディレクトリにコピーするのは大変な作業です。
そこで、Node.jsはパッケージ管理ツールを提供しており、あるモジュールやモジュールを共有リポジトリにパッケージ形式で公開することができます。このようにすることで、他の人はパッケージ名を知っていれば、パッケージ管理ツールのコマンドでそのモジュールを自分のプロジェクトにインストール(デフォルトではプロジェクトのnode_modulesディレクトリにインストール)し、自分のコードでパッケージ名を使用してモジュールをインクルードすることができます。
このツールがNPMです。
NPM を使ってモジュールパッケージをインストールする。
Node.js をインストールする際に、NPMが内蔵されています。NPM コマンドを使用して、望む操作を実行できます。
$ npm -v 8.11.0
npm -v コマンドを実行することで、NPMのバージョン番号が表示されます。例えば現在のバージョンは8.11.0です。
npm install パッケージ名 と入力することで、インストールしたいパッケージをインストールすることができます。
インストールしたいパッケージを探すためには、npmjs.orgかGitHubでプロジェクトに必要なものを探す必要があります。
例えば、日付と時刻を処理するアプリを作る場合、moment.jsをインストールする必要があります。プロジェクトのディレクトリ内でインストールする前に、まずプロジェクト内で設定を初期化することをおすすめします。
$ npm init -y
npm init -yコマンドを使用して、簡単に設定を生成できます。
プロジェクトディレクトリの下にpackage.jsonファイルが生成され、以下のような内容になります。
{
"name": "examples",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
このtypeプロパティをmoduleに設定することで、Node.jsは.jsファイルをES Modules規則で処理できるようになります。
ここでは、生成されるこのファイルのフィールド名は解説しませんが、
インストールしたいmoment.jsパッケージをインストールし続けます。
npm install moment --save
moment.jsライブラリの名前はmomentというので、上記のnpm installコマンドを実行しました。
もし異常がなければ、すぐにインストールが完了し、インストールされたモジュールのバージョン情報が出力されます。
ここではMoment.jsバージョン2.24.0をインストールしました。注目すべきは、npm install を実行する際に--saveパラメーターを付けたことです。
このパラメーターは、パッケージが正常にインストールされた後に自動的にpackage.jsonファイルが更新され、dependenciesプロパティー内にインストールしたパッケージの名前とバージョン情報が追加されることを意味します。
{
"name": "examples",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"moment": "^2.24.0"
}
}
package.json ファイルが変更され、dependencies 内容が追加されたことが示されています。
このような場合の利点は、他の人にプロジェクトを管理したり、新しいマシンに移行させたりする際、プロジェクトの依存パッケージを再インストールする必要がなくなることです。
プロジェクトディレクトリ内で引数なしのコマンド npm install を入力するだけで、package.json の dependencies 内容に基づいて適切な依存パッケージを自動的にインストールします。
自分のモジュールを NPM に公開する場合、他のユーザーがモジュールをインストールする際にも、dependencies 内容に基づいて自動的に依存パッケージをインストールします。
今、moment.js はインストールが完了しています。
それはプロジェクトディレクトリの node_modules サブディレクトリにインストールされました。
そこにある moment サブディレクトリ内にインストールしたモジュールがあります。
依存する他のモジュールがある場合、これらも node_modules ディレクトリに同時にインストールされます。
つぎに、プロジェクトのディレクトリ内やどんなサブディレクトリ内でも、moment というパッケージ名でモジュールをインポートすることができます。
const moment = require('moment');
console.log(moment().format());
// 2022-03-16T22:20:16+08:00
Node.jsは、モジュールを探すための規則に従って、パッケージ名をインポートするときにモジュールの場所を検索します。
まずは、現在のディレクトリのnode_modulesディレクトリを優先的に検索します。
見つからない場合は、上位のディレクトリを再帰的に検索し、見つかるかOSのルートディレクトリに到達するまで続けます。
Node.js のパッケージの中には、ターミナルでコマンドを実行することができるものがあります。
Webpack、ESLint、Babelなどのライブラリは、cliスクリプトを提供しており、インストールしたユーザーはcliスクリプトのコマンドを使ってファイルを処理できます。
コマンドラインでスクリプトを実行するには、システムディレクトリにインストールする必要があります。
このとき、npmコマンドのオプション-gを使って、モジュールをシステムディレクトリ(通常はOSのデフォルトのNodeインストールディレクトリ)にインストールできます。
そうすれば、コマンドラインでそれらのライブラリのコマンドを実行することができるようになります。
例えば、eslintモジュールをインストールすると、これはJSの文法と書き方の検証ツールであるeslintコマンドを提供します。
コマンドラインでeslintコマンドを実行できるようにするには、
システムディレクトリにインストールすることができます。
npm -g install eslint
これにより、私たちはJSコードをチェックしたいディレクトリでeslintコマンドを実行することができます。
例えば、ziyue.jsをチェックするなら、まずプロジェクトのディレクトリで、eslint --initコマンドを実行して、.eslintrc.jsの設定を初期化する必要があります。
その後、コマンドを実行します。
eslint ziyue.js
この時、コマンドラインがチェックの結果を出力します。
結果には、JSのチェックのためにStandard規範がデフォルト設定されていて、Standardはエンジンが自動的にセミコロンを補完する書き方を採用しているので4つの文法エラーが含まれています。
また、ファイルの最後には空行を保持しなければなりません。 eslintの使用に関しては、このコースのプロジェクト化の部分でさらに深く話します。
NPM Scriptsとは
もし、モジュールをシステムディレクトリの下にインストールしたくない場合で、現在のプロジェクトのディレクトリの下でスクリプトコマンドを実行したい場合には、-gパラメータを用いずにグローバルインストールせず、node_modulesディレクトリにインストールすることが可能です。
その場合、コマンドラインから直接スクリプトコマンドを実行することはできません。そのコマンドをOSが認識できないからですが、NPM Scriptsを使って実行することはできます。
NPM Scriptsとは、package.jsonファイルの中にscripts属性を設定し、その中にスクリプトコマンドを指定することを指しています。
// package.json
{
... //その他
"scripts": {
"eslint": "eslint ziyue.js"
}
}
ziyueプロジェクトのディレクトリのpackage.jsonファイルのscriptの下に、eslintコマンドを追加します。
これで、ziyueディレクトリ下でnpm run eslintを実行することで、対応するコマンドを実行できます。
このとき、eslintを-gオプションでシステムディレクトリにインストールする必要はありません。直接、現在のプロジェクトのnode_modulesディレクトリ下にインストールすればいいです。
NPM Scriptsは対応するNodeコマンドを実行できるのは、NPMがモジュールをインストールするとき、モジュール自体だけでなく、モジュールの中のコマンドラインスクリプトをnode_modulesディレクトリの.binサブディレクトリにインストールし、NPM Scriptsの実行時にシステムの環境変数PATHにnode_modules/.binディレクトリを含めるように設定するからです。
つまり、私たちが以下を実行すると、
npm run eslint
次のように実行されることと同じです。
node ./node_modules/.bin/eslint ziyue.js
NPMの特徴なコマンドとして、
「start」、「test」、「publish」があります。
多数のNPM Scriptsコマンドは、「npm run コマンド名」を実行する必要がありますが、特殊な名前のコマンドは、「run」を省略して、「npm コマンド名」で実行することができます。
例えば、「start」と「test」コマンドがそれに当たります。
「start」コマンドは通常、プロジェクトを起動するために使用されます。
例えば、Webプロジェクトの開発時には、開発環境のHTTPサーバーを起動するために「start」コマンドを設定します。
「test」コマンドは通常、プロジェクトのユニットテストを設定するために使用されます。ユニットテストフレームワークを起動し、テストケース(test case)を実行します。
また、NPM Scriptsにないコマンドは、NPM自体の指示を実行するために使用できます。
「npm install」コマンドはモジュールをインストールするための指示であり、「npm init」コマンドはデフォルトのpackage.json設定を作成するための指示です。
他のコマンドには、自分自身のモジュールパッケージをNPMサーバーに公開または更新するための「npm publish」コマンドがあります。
ここで注意することは、これらのNPM自身のコマンドには「run」が付きませんが、scriptsプロパティで同名のコマンドを定義することもできます。
例えば、「install」というNPM Scriptsを定義できます。
{
...
"scripts": {
"install": "do something"
}
}
この時、npm run installを実行すると、デフォルトのnpm installコマンドではなく、このスクリプトコマンドが実行されます。
Node.jsを使ってアプリを開発する方法を学びます
ランダム文章ジェネレーターのAPPを開発する。
このアプリを通じて、node環境でfs、process、readlineモジュールをどのように使うか、自分のモジュールを作成する方法、そして第三のライブラリをインストールしてインポートする方法を学ぶことができます。
まずこのアプリケーションの要件を理解しましょう。
ランダムな文章ジェネレーターの機能は、コーパスの設定とユーザーが入力したルールに基づいて、可変長のテキストをランダムに生成することです。
その中の文章は流暢ながら、くだりが続いていることがあります。
このようなテキストは、Web開発においてレイアウトやコンテンツの表示効果を特定の数量でテストするために使用できるほか、データベースやファイルの読み書きをテストするためにも活用できます。
また、単純に楽しむためのものとしても使用することができます。
以下の機能を実現する必要があります
コーパスを読み込んで解析する
コーパスからランダムなアルゴリズムでランダムに選択する
文字列テンプレートのパラメーターを置換する
文章の内容を組み合わせる
文章を出力する
ユーザーとのインタラクションを考慮すれば、次のことを完了する必要があります
コマンドライン入力のパラメータを受け取る
コマンドライン使用ガイドをユーザーに提供する
テキストの内容の形式と保存を出力する
対応する技術点は以下の通りです
fsモジュールを使用してコーパスファイルの内容を読み取る
要求に合うランダムなモジュールを実装する
正規表現と文字列テンプレートの置換と文字列の結合を使用して文章を生成する
process.argvを使用してユーザーのパラメータを受け取り、パラメーターに応じて異なる内容を出力する
fsモジュールとバイナリモジュールを使用して生成した文章内容をテキストと画像形式に保存する
新しいプロジェクト、bullshit_generatorという名前を付けました。
プロジェクトのディレクトリ構造は下記の通りです。
.
├── corpus
│ └── data.json
├── index.js
├── lib
│ ├── generator.js
│ └── random.js
├── package.json
└── output
corpusフォルダには、jsonファイルであるdata.jsonがあります。index.jsはメインのプログラムファイルで、実行可能なNode.jsスクリプトです。
libフォルダ内には、プロジェクトに必要なライブラリファイルがあります。
ここでは外部のライブラリを依存しないように、generator.jsモジュールを使って記事の内容を生成し、乱数モジュールを使ってランダムアルゴリズムを提供します。
package.jsonはプロジェクトの設定ファイルです。outputフォルダには出力結果が格納されます。
次のいくつかのレッスンでは、上記の技術を使って文章ジェネレータアプリケーションを実装します。
TODO
作業中…