Node.jsエコシステムを体験しよう =================================== TypeScriptはJavaScriptへの変換を目的として作られた言語です。公式の処理系がありますが、それで変換すると、JavaScriptが生成されます。勉強目的で実行するには、現在のところ、いくつかのオプションがあります。 このなかで、とりあえず安定して使えて、比較的簡単なのはts-nodeですね。 * TypeScriptのウェブサイトのplayground [#]_: 公式のコンパイラで変換してブラウザで実行 * 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 がリリースされました [#]_ ) * 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章以降で取り扱うので、必要になったら戻って来てください。 .. [#] https://www.typescriptlang.org/play/index.html .. [#] https://deno.land/v1 Node.jsのインストール ------------------------------------ Node.jsは公式の https://nodejs.org からダウンロードしてください。あるいは、chocolateyやHomebrew、macportsなどのパッケージマネージャなどを使ってインストールすることも可能です。もし、複数のバージョンを切り替えて検証する場合にはnvmが利用できます。ただし、フロントエンド開発においては、コードは変換してから他の環境(ブラウザやらクラウドのサービス)上で実行されますし、基本的に後方互換性は高く、バージョン間の差もそこまでないため、最新のLTSをとりあえず入れておけば問題ないでしょう(ただし、AWS Lambdaなどの特定の環境での動作を確認したい場合はのぞく)。 .. todo:: あとで書く Node.jsをインストールすると、標準のパッケージマネージャの npm もインストールされます。もしかしたらパッケージマネージャの種類によってはインストールされない場合もあるので、その場合は追加インストールしてください。 npmコマンドはパッケージのダウンロードのためにインターネットアクセスをします。もし、社内プロキシなどがある場合はnpmのインストール後に設定しておくのをおすすめします。 .. code-block:: sh :caption: プロキシの設定 npm config set proxy http://アカウント名:パスワード@プロキシーのURL npm config set https-proxy http://アカウント名:パスワード@プロキシーのURL ``package.json`` の作成と ``ts-node`` のインストール ------------------------------------------------------------- 最初に作業フォルダを作り、 ``package.json`` を作成します。 .. code-block:: bash $ 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`` を起点に解析していくと効率よく探すことができます。 この ``npm init`` コマンドで作成される ``package.json`` は、とりあえずフォルダ名から付与された名前、固定のバージョン(1.0.0)、空の説明が入っています。 このファイルはパッケージのリポジトリであるnpmjs.orgにアップロードする際に必要な情報もすべて入ります。 仕事のコードやハンズオンのプロジェクトを間違って公開しないように(することもないと思いますが)、 ``"private": true`` を書き足しておきましょう。 .. code-block:: json { "name": "env", "version": "1.0.0", "description": "", "private": true : } 次に必要なツールをインストールします。npm installで、ts-nodeとtypescriptを入れます。 ``--save-dev`` をつけると、開発に必要だが、リリースにはいらないという意味になります。 .. code-block:: bash $ npm install --save-dev ts-node typescript もし、本番環境でもts-nodeを使ってビルドしたい、ということがあれば ``--save-dev`` の代わりに ``--save`` をつけます。 .. code-block:: bash $ npm install --save ts-node ``package.json`` を見ると、項目が追加されているのがわかりますね。また、 ``package-lock.json`` という、環境を構築したときの全ライブラリのバージョン情報が入ったファイルも生成されます。このファイルを手で修正することはありません。 .. code-block:: 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以外の場合の動作です。 .. list-table:: :header-rows: 1 :widths: 10 20 - * ``npm install`` * dependenciesとdevDependenciesの両方をインストールする。 - * ``npm install --prod`` * dependenciesのみをインストールする。 - * ``npm ci`` * dependenciesとdevDependenciesの両方をインストールする。package-lock.jsonは更新しない。 - * ``npm ci --prod`` * dependenciesのみをインストールする。package-lock.jsonは更新しない。 インストールしたコマンドの実行 -------------------------------------------- npmコマンドでインストールするパッケージは、プログラムから使うライブラリ以外に実行できるコマンドを含むものがあります。先ほどインストールしたtypescriptとts-nodeは両方ともこれを含みます。コマンドは、node_modules/.bin以下にインストールされています。これを直接相対パスで指定しても良いのですが、専用のコマンドもあります。 ts-nodeを気軽に試すREPL(1行ごとに実行されるインタプリタ)の実行もできます。 .. code-block:: bash $ npx ts-node > console.log('hello world') hello world ``package.json`` のscriptsのセクションに登録すると、npmコマンドを使って実行できます。 .. code-block:: json "scripts": { "start": "ts-node" } "scripts"にはオブジェクトを書き、その中にはコマンドが定義できます。ここでは ``start`` コマンドを定義しています。コマンドが実行されたときに実行されるコードを書けます。ここではnode_modules/.bin以下のコードをパスを設定せずに書くことができます。 ``npm run [コマンド名]`` とシェルで実行すると、この ``scripts`` セクションのコマンドが実行されます。 .. code-block:: bash $ 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の処理系を使って生成できます。 .. code-block:: bash $ npx tsc --init message 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ではエラーとなるようにしています。 .. code-block:: ts :caption: 最初のサンプルコード(first.ts) const personName: string = '小心者'; console.log(`Hello ${personName}!`); 実行するにはnpx経由でts-nodeコマンドを実行します。 .. code-block:: bash $ npx ts-node first.ts Hello 小心者! 今後のチュートリアルでは基本的にこのスタイルで実行します。 まとめ ------------- 本章では次のようなことを学んで来ました。 * JavaScriptのエコシステムとpackage.json * サンプルを動かすための最低限の環境設定 次章からはさっそくコーディングの仕方を学んで行きます。