Node.jsエコシステムを体験しよう
TypeScriptはJavaScriptへの変換を目的として作られた言語です。公式の処理系がありますが、それで変換すると、JavaScriptが生成されます。勉強目的で実行するには、現在のところ、いくつかのオプションがあります。このなかで、とりあえず安定して使えて、比較的簡単なのはts-nodeですね。
TypeScriptのウェブサイトのplayground1: 公式のコンパイラで変換してブラウザで実行
tsc + Node.js: 公式のコンパイラで変換してからNode.jsで実行
babel + ts-loader + Node.js: Babel経由で公式のコンパイラで変換してからNode.jsで実行
babel + @babel/preset-typescript + Node.js: Babelで型情報だけを落として簡易的に変換してNode.jsで実行
ts-node: TypeScriptを変換してそのままNode.jsで実行する処理系
Deno: TypeScriptをネイティブサポートした処理系(2020-05-13 に 1.0 がリリースされました2 )
Bun: 新しいJavaScript/TypeScriptの処理系
Node.jsはJavaScriptにファイル入出力やウェブサーバー作成に必要なAPIなどを足した処理系です。本章では、TypeScriptの環境整備をするとともに、Node.jsを核としたエコシステムの概要を説明します。プログラミング言語を学んで書き始める場合、言語の知識だけではどうにもなりません。どこにソースコードを書き、どのようにビルドツールを動かし、どのように処理系を起動し、どのようにテストを行うかなど、言語周辺のエコシステムを学ばないと、どこから手をつけて良いかわかりません。本章で紹介するエコシステムの周辺ツールや設定ファイルは以下の通りです。
Node.js: 処理系
npmコマンド: パッケージマネージャ
package.json: プロジェクトファイル
依存パッケージの管理
scripts
で開発用のタスクのランチャーとして利用
npxコマンド: Node.js用のnpmパッケージで提供されているツールの実行
TypeScript関連のパッケージ
tsc: TypeScriptのコンパイラ(プロジェクト用のTypeScriptの設定ファイルの作成)
ts-node: TypeScript変換しながら実行する、Node.jsのラッパーコマンド
まずはNode.jsをインストールしてnpmコマンドを使えるようにしてください。なお、本章ではゼロから環境を構築していきますが、ハンズオンのチーム教育などで、構築済みの環境をシェアする場合には次の節は飛ばしてください。コードを書くスキルに対して、環境構築に必要なスキルは数倍難易度が高いです。エコシステムを完全に理解してツール間の連携を把握する必要があります。ただし、そのために必要な知識はコードを書いていくうちに学びます。どうしても難易度が高い作業が最初に来てしまい、苦手意識を広げてしまう原因になってしまいます。環境構築は、本章と、5章以降で取り扱うので、必要になったら戻って来てください。
Node.jsのインストール
Node.jsは公式のhttps://nodejs.org からダウンロードしてください。あるいは、chocolateyやHomebrew、macportsなどのパッケージマネージャなどを使ってインストールすることも可能です。もし、複数のバージョンを切り替えて検証する場合にはnvmが利用できます。ただし、フロントエンド開発においては、コードは変換してから他の環境(ブラウザやらクラウドのサービス)上で実行されますし、基本的に後方互換性は高く、バージョン間の差もそこまでないため、最新のLTSをとりあえず入れておけば問題ないでしょう(ただし、AWS Lambdaなどの特定の環境での動作を確認したい場合はのぞく)。
課題
あとで書く
Node.jsをインストールすると、標準のパッケージマネージャの npm もインストールされます。もしかしたらパッケージマネージャの種類によってはインストールされない場合もあるので、その場合は追加インストールしてください。
npmコマンドはパッケージのダウンロードのためにインターネットアクセスをします。もし、社内プロキシなどがある場合はnpmのインストール後に設定しておくのをおすすめします。
npm configset proxy http://アカウント名:パスワード@プロキシーのURLnpm configset https-proxy http://アカウント名:パスワード@プロキシーのURL
package.json
の作成とts-node
のインストール
最初に作業フォルダを作り、package.json
を作成します。
$ mkdir try_ts$cd try_ts$ npm init -y{"name":"try_ts","version":"1.0.0","description":"","main":"index.js","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"keywords":[],"author":"","license":"ISC"}
package.json
はNode.jsを使ったプロジェクトの核となるファイルです。次のような情報が入ります。
プロジェクト自身のさまざまな情報
プロジェクトが依存する(実行で必要、もしくは開発に必要)ライブラリの情報
プロジェクトのビルドやテスト実行など、プロジェクト開発に必要なタスクの実行
他の人が行なっているプロジェクトのコードを見るときも、まずはpackage.json
を起点に解析していくと効率よく探すことができます。このnpminit
コマンドで作成されるpackage.json
は、とりあえずフォルダ名から付与された名前、固定のバージョン(1.0.0)、空の説明が入っています。このファイルはパッケージのリポジトリであるnpmjs.orgにアップロードする際に必要な情報もすべて入ります。仕事のコードやハンズオンのプロジェクトを間違って公開しないように(することもないと思いますが)、"private":true
を書き足しておきましょう。
{"name":"env","version":"1.0.0","description":"","private":true:}
次に必要なツールをインストールします。npm installで、ts-nodeとtypescriptを入れます。--save-dev
をつけると、開発に必要だが、リリースにはいらないという意味になります。
$ npm install --save-dev ts-node typescript
もし、本番環境でもts-nodeを使ってビルドしたい、ということがあれば--save-dev
の代わりに--save
をつけます。
$ npm install --save ts-node
package.json
を見ると、項目が追加されているのがわかりますね。また、package-lock.json
という、環境を構築したときの全ライブラリのバージョン情報が入ったファイルも生成されます。このファイルを手で修正することはありません。
{"dependencies":{"ts-node":"^8.0.2"},"devDependencies":{"typescript":"^3.3.1"}}
また、node_modules
フォルダができて必要なライブラリなどがインストールされていることがわかります。他の言語と異なり、基本的にNode.jsは現在いるフォルダ以外のところにインストールすることはありません(キャッシュはありますが)。複数プロジェクト掛け持ちしているときも、プロジェクト間でインストールするライブラリやツールのバージョンがずれることを心配する必要はありません。
プロジェクトをチーム間で共有するときは、このpackage.json
があるフォルダをバージョン管理にシステムに入れます。ただし、node_modules
は配布する必要はありません。.gitignore
などに名前を入れておくと良いでしょう。
プロジェクトフォルダ共有後の環境構築
チーム内では、gitなどでプロジェクトのソースコードを共有します。JavaScript系のプロジェクトでは、その中にpackage.json
とpackage-lock.json
があり、デプロイ時に環境を作ったり、共有された人は環境を手元で再現したりするのが簡単にできます。
以下は、環境変数NODE_ENVが未設定またはproduction以外の場合の動作です。
| dependenciesとdevDependenciesの両方をインストールする。 |
---|---|
| dependenciesのみをインストールする。 |
| dependenciesとdevDependenciesの両方をインストールする。package-lock.jsonは更新しない。 |
| dependenciesのみをインストールする。package-lock.jsonは更新しない。 |
インストールしたコマンドの実行
npmコマンドでインストールするパッケージは、プログラムから使うライブラリ以外に実行できるコマンドを含むものがあります。先ほどインストールしたtypescriptとts-nodeは両方ともこれを含みます。コマンドは、node_modules/.bin以下にインストールされています。これを直接相対パスで指定しても良いのですが、専用のコマンドもあります。
ts-nodeを気軽に試すREPL(1行ごとに実行されるインタプリタ)の実行もできます。
$ npx ts-node> console.log('hello world')hello world
package.json
のscriptsのセクションに登録すると、npmコマンドを使って実行できます。
"scripts":{"start":"ts-node"}
"scripts"にはオブジェクトを書き、その中にはコマンドが定義できます。ここではstart
コマンドを定義しています。コマンドが実行されたときに実行されるコードを書けます。ここではnode_modules/.bin以下のコードをパスを設定せずに書くことができます。npmrun[コマンド名]
とシェルで実行すると、このscripts
セクションのコマンドが実行されます。
$ npm run start> console.log('hello world')hello world
だいたい、次のようなコマンドを定義することが多いです。
start
/serve
: パッケージがウェブアプリケーションを含む場合はこれを起動test
: テストを実行lint
: コードの品質チェックを行うbuild
: ビルドが必要なライブラリではビルドを実行して配布できるようにする
ビルドツールや処理系、テスティングフレームワークなどは、プロジェクトによって千差万別ですが、このscripts
セクションを読むと、どのようにソースコードを処理したり、テストしたりしているかがわかります。これは、プロジェクトのコードを読むための強い武器になります。
また、このコマンド実行まではWindowsだろうが、Linuxだろうが、macOSだろうが、どれでもポータブルに動作します。Node.jsとnpmコマンドさえあれば、開発機(Windows、macOS)、CIサーバー(Linux)、本番環境(Linux)で動作します。もちろん、中で動作させるプログラムに、Node.js以外のOSのコマンドを書くとそこのポータビリティは下がりますが、それに関してはおすすめパッケージの中でポータブルなscripts
セクションを書くのに使えるパッケージを紹介します。
TypeScriptの環境設定
TypeScriptを使うには、いくつか設定が必要です。JavaScript系のツールのビルドは大きく分けて、2つのフェーズがあります。
コンパイル: TypeScriptや最新のJavaScript文法で書かれたコードを、実行環境にあわせたJavaScriptに変換
バンドル: ソースコードは通常、整理しやすいクラスごと、コンポーネントごとといった単位で分けて記述します。配布時には1ファイルにまとめてダウンロードの高速化、無駄な使われてないコードの排除が行われます。
前者のツールとしては、TypeScriptやBabelを使います。後者は、webpack、Browserify、Rollup、Parcelなどがあります。ただし、後者は大規模なアプリケーションでなければ必要ありませんので、5章以降で紹介します。
何も設定せずとも、TypeScriptのコンパイルは可能ですが、入力フォルダを設定したい、出力形式を調整したい、いくつかのデフォルトでオフになっている新しい機能を使いたいなどの場合は設定ファイルtsconfig.json
を作成します。このファイルの雛形はTypeScriptの処理系を使って生成できます。
$ npx tsc --initmessage TS6071: Successfully created a tsconfig.json file.
あとはこのJSONファイルを編集すれば、コンパイラの動作を調整できます。TypeScriptをNode.jsで実行するだけであれば細かい設定は不要ですが、4章ではオプションを使わないといけない文法にもついても紹介します。
エディタ環境
現在、一番簡単に設定できて、一番精度の高い補完・コードチェックが自動で行われるのがVisual Studio Codeです。Windowsユーザーも、Linuxユーザーも、macOSユーザーも、これをダウンロードしてインストールしておけば間違いありません。何も拡張を入れなくても動作します。
プロジェクトごとの共通の設定も、.vscodeフォルダに設定を書いてリポジトリに入れるだけで簡単にシェアできる点も、プロジェクトで使うのに適しています。よりアドバンスな設定やツールに関しては環境構築の章で紹介します。
ts-nodeを使ったTypeScriptのコードの実行
それでは適当なコードを書いて実行してみましょう。本来はこのコードはJavaScriptと完全互換で書けるのですが(次章で解説します)、あえて型を定義して、通常のNode.jsではエラーとなるようにしています。
constpersonName:string='小心者';console.log(`Hello${personName}!`);
実行するにはnpx経由でts-nodeコマンドを実行します。
$ npx ts-node first.tsHello 小心者!
今後のチュートリアルでは基本的にこのスタイルで実行します。
まとめ
本章では次のようなことを学んで来ました。
JavaScriptのエコシステムとpackage.json
サンプルを動かすための最低限の環境設定
次章からはさっそくコーディングの仕方を学んで行きます。