Visual Studio Code & TypeScriptを使い、ブラウザ用の開発設定についてのメモです。以下のような条件の開発設定です。
- 複数のTypeScriptファイルに分割して開発
- TypeScriptのコードは、Node.jsからも利用できる(Module対応)
- Visual Studio Codeからデバッグできる
- TypeScriptのasync/await構文に対応する
この記事で扱う環境のバージョンは以下の通りです。
Visual Studio Code | 1.10.1 |
Nod.js | 6.5.0 |
TypeScript | 2.2.1 |
環境構築
TypeScript関連のセットアップが終わったら、Visual Studio Codeに「Debugger for Chrome」拡張機能をインストールします。もし、Chromeがインストールされていない場合は、Chromeもインストールします。
[topBannar]
tsconfig.json
TypeScriptのプロジェクトのディレクトリ(.tsファイルが置いてあるディレクトリ)に、「tsconfig.json」というファイルを作成し、設定を記述します。以下のような感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{ "compilerOptions": { "target": "ES5", "module": "amd", "sourceMap": true, // 出力するファイル名を指定 "outFile": "./src/main.js", "lib": [ "dom", "es5", "scripthost", "es2015.promise" ] } } |
ポイントは3つ
- modlue に amd を設定(AMD形式のモジュールを使用)
- outFile を指定(今回は、./src/main.jsを指定しましたが、ここは場合によって変更してください)
- lib を指定(特に、「es2015.promise」が重要です)
modlueを指定しない場合、トランスパイルされたファイルがoutFileに指定されたファイルにすべて結合されて出力されるため、ブラウザ上で動作させる場合、こちらの方が便利かもしれません。modlueにamdを指定しているため、outFileの設定は必須ではありません。ただ、これを設定しないと、tsファイルごとにjsファイルとmapファイルが生成され、ディレクトリが汚れます。そのため、少なくとも開発中は一つのjsファイルにまとめるように設定しています(もしくは、outDirで出力ディレクトリを変えるのも良いかもしれません。)。libの指定は、async/awaitを使うために、重要です。awaitで待つ関数はPromiseオブジェクトを返さないといけないのですが、ここで指定しておかないと、インテリセンスに文句を言われました。そのほかのライブラリはデフォルトのもののようです。
.vscode/tasks.json
「.vscode/tasks.json」ファイルがない場合、プロジェクトのビルド(Ctrl + Shift + B)を行うと、「タスクランナーが構成されていません。」と出ると思います。そこで、右端の「タスクランナーの構成」をクリックし、「TypeScript – tsconfig.json」を選択します。すると、「.vscode/tasks.json」が作成されます。内容は特に編集する必要はありません。
.vscode/launch.json
次に、デバッグ用の設定を記述します。デバッグを開始すると、デバッグ構成を選択できますが、デフォルトですとあまりいい感じにならないため、手動で「.vscode/launch.json」ファイルを作成し、以下のように記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
{ "version": "0.2.0", "configurations": [ { "name": "Launch Local", "type": "chrome", "request": "launch", // 読み込むHTMLファイルを指定 "file": "${workspaceRoot}/index.html", "trace" :true, "sourceMaps": true, "runtimeArgs": [ "--allow-file-access-from-files" ] } ] } |
このように記述すると、デバッグを開始すると、ディレクトリ下の「index.html」ファイルをChromeで開き、デバッグができるようになります。「runtimeArgs」に「–allow-file-access-from-files」を渡しておくことで、ローカルファイルを読み込むようなJavaScriptの実行もデバッグできます。ちなみに、すでにChromeが起動しているといろいろとうまくいきませんので、一旦終了しておく必要があります(Macの場合は、プロセスを終了させておきます)。もし、起動中のChromeを使用したい場合は、requestにattachを指定し、Chromeの起動設定を変更する必要があります。
index.html
Chromeから最初に読み込むHTMLファイルを記述します。以下のような感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title> Test </title> </head> <body> <!-- javascriptの読み込み --> <script src="https://www.promisejs.org/polyfills/promise-7.0.4.min.js"></script> <script data-main="./src/main.js" src="require.js"></script> </body> </html> |
AMD方式でトランスパイルするように設定したため、HTMLからJavaScriptファイルを読み込むためには、RequireJSを使用します。「require.js」ファイルをダウンロードし、index.htmlと同じディレクトリに配置してください。そして、
1 2 3 |
<script data-main="./src/main.js" src="require.js"></script> |
のように「data-main」を使って、対象のJavaScriptファイルを読み込むようにします。また、TypeScriptでasync/awaitを使う場合、Promiseが必要になるのですが、PromiseはIE11では対応していないため、PolyFillのライブラリも読み込むようにしておきます。
テスト
プロジェクトディレクトリは、以下のようなファイル構成とします。
- .vscode
- launch.json
- tasks.json
- index.html
- require.js
- main.ts
- module.ts
- src
- main.js
- main.js.map
このうち、「launch.json」「tasks.json」「index.html」「require.js」は先に述べた通りです。また、「src」ディレクトリ以下はビルドすると自動生成されます。main.tsとmod.tsは、以下の通りです。なお、エントリポイントとなるtsファイルの名前とトランスパイル後のjsファイルの名前は同じにしておく必要があるようです。
1 2 3 4 5 |
import Hello = require("./mod"); var hello:Hello = new Hello(); hello.Show(); |
1 2 3 4 5 6 7 8 |
class Hello { public Show() { console.log("Hello!!"); } } export = Hello; |
以下、注意事項です。
- エントリポイントとなるtsファイルとトランスパイル後のjsファイル名とが異なった場合、実行されません
- module.tsというファイル名にすると、いろいろとトラブりました
デバッグを開始すると、Chromeが起動します。ただ、ブレークポイントの設定が間に合わないのか、うまくブレークポイントを設定しても止まらないことがあります。その場合、Visual Studio Codeの方から「再起動」するとうまくいきました。
以上の設定で、tsファイル側にブレークポイントを仕掛けてデバッグすることができます。また、TypeScriptのモジュール仕様も利用することができます。また、async/awaitも対応しています。例えば、mod.tsを以下のように書き換えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
class Hello { showDelay() { return new Promise(resolve => { window.setTimeout( () => { console.log("Hello 2"); resolve(); }, 1000); }); } public async Show() { console.log("Hello 1"); await this.showDelay(); console.log("Hello 3"); } } export = Hello; |
これを実行すると、Hello 1が出力されたのちに、1秒後にHello2→Hello 3と表示されます。IE11でも問題なく動作します。(Promiseについては、こちらで紹介しています。)
[bottomBannar]