2017年5月8日月曜日

VSCodeでThree.jsの開発環境を整える(3)

Visual Studio Codeで、Three.jsの開発環境を構築しています。このポストでは、VSCodeのデバッガ機能を利用してブレークポイントを打ったりすることができることまでが目標です。ブラウザ環境としてはChromeかFirefoxが現実的な選択肢だと思うけど、今回はまずFirefoxでデバッグすることを考えます。

Debugger for Firefox をVSCodeにインストールする

まずはVSCodeにFirefoxのデバッガ拡張をインストールします。これは単純に以下のプラグインをインストールすればOK。
https://marketplace.visualstudio.com/items?itemName=hbenl.vscode-firefox-debug
この拡張をインストールすると、デバッガのlaunch.jsonファイルの編集時、Add Configuration...した場合にFirefox:*系の設定項目が選べるようになります。

Webpackがビルド時にSourceMapを出力するように設定する

前回のポストで設定したwebpack.config.jsに設定を追加して、SourceMapというデバッグ用のファイルをビルド時に出力するようにします。SourceMapというには簡単に言えば、webpackなどのビルドツールでバンドルされたJavaScriptファイルと、バンドル前のソースコードの対応付けを記述したファイルで、これが存在することによってバンドル前のソースコード上でブレークポイントを指定したりすることが可能になるもののようです。

具体的には、module.exportsの辞書配列の中に以下の項目を追加するだけです。
devtool: "source-map"
source-map以外にも選択肢がいくつかあるようですが、今回はsource-mapを指定しました。ビルド時の処理時間と、取得できるデバッグ情報の精度とのトレードオフのようなので、必要に応じて調べれば良いと思います。
上記の設定で再度ビルドをし直すと、outputでの出力JavaScript名がbundle.jsだった場合にbundle.js.mapというSourceMapファイルが出力されます(設定によって、出力されるものの内容も変わるようです)。

launch.jsonにFirefox用の設定を追加する

デバッグメニューからAdd Configuration...を選択し、Firefox: Launch (Server) およびFirefox: Attachの2つを追加します。SourceMapに関わる部分はpathMappingsというキー項目だけなので、これをそれぞれに追加します。私の環境で動作した設定は下記のもので、Extensionのサイトのドキュメントに書いてあるものとは違いましたが、要するにurlという項目がブラウザがアクセスしている先、pathというのが対応するソースのローカルでのファイルパスを指せば良いようです。デバッグする対応のページで対象のurlがどこを指しているかは、ツール>ウェブ開発>デバッガーを開き、「ソース」というリストの中にwebpack://というスキームのURLが見つかると思うので、それがどこを指しているのかを確認し、プロジェクト内のバンドル前のソースファイルと対応するように適宜変更すれば良いと思います。
{
    "version": "0.2.0",
    "configurations": [
        
        {
            "type": "firefox",
            "request": "attach",
            "name": "Attach",
            "pathMappings": [
                {
                    "url": "webpack://",
                    "path": "${workspaceRoot}"
                }
            ]
        },
        {
            "type": "firefox",
            "request": "launch",
            "reAttach": true,
            "name": "Launch localhost",
            "url": "http://localhost:8080/index.html",
            "webRoot": "${workspaceRoot}/htdocs/",
            "pathMappings": [
                {
                    "url": "webpack://",
                    "path": "${workspaceRoot}"
                }
            ]
        }
    ]
}

Firefoxを使ってデバッグする(Launch)

上記例では、Launch localhostという項目を選んでデバッグを実行(F5)すると、Firefoxが起動してurl項目に設定したサイトにアクセスするようになります。このとき、ソースファイル側(webpackでバンドルされる前のファイル)にブレークポイントを打っていると、そこで処理が停止するようになります。詳しく調べていないけど、起動した後にFirefox側でページをリロードしないといけないケースがあったのは、多分イベントの発火のタイミングのような気がします。
ちなみにreAttachという項目をtrueにすると当該デバッグ終了時にFirefoxは合わせて終了し、デバッグのRestart時にはFirefoxごと再起動します。これでもいいんだけどデバッグ時には通常なんども繰り返すことになると思うので、通常はAttachモードを選んだ方がよさそうです。

Firefoxを使ってデバッグする(Attach) 

Attachモードは、すでに実行中のFirefoxにVSCodeから接続するので、Firefox自体の起動終了を伴わず、効率的です。ただし、デバッグを外部ツールから利用可能にするために最初にFirefox自体の設定を変更する必要があります。 設定の詳細についてはExtensionのドキュメントのAttachという項目を見てその通りに設定すれば良いです。設定画面へは、about:configというアドレスをアドレスバーに入力します。 https://marketplace.visualstudio.com/items?itemName=hbenl.vscode-firefox-debug
上記の必要な設定を行った上で、Firefoxはコマンドラインから以下のようにオプション付きで起動する必要があります。macOSの場合、
$ /Applications/Firefox.app/Contents/MacOS/firefox -start-debugger-server -no-remote
のようにします。-no-remoteオプションはローカルホスト以外からのアクセスを拒否する設定なので、環境によっては除外します。

上記で起動したFirefox上でたとえばhttp://localhost:8080/index.htmlにアクセスしたうえで、VSCodeのデバッグメニュー上からAttachメニューを選択し実行(F5)すると、Launch時と同じようにデバッグが実行可能になります。Launch時と同様に、デバッグ実行後、ページを再読み込みしないといけないケースもあるようです。

2017年5月7日日曜日

VSCodeでThree.jsの開発環境を整える(2)

前のポストでVisual Studio Code上でコード補完付きでコーディングが可能な状態になったので、これをブラウザ上で実行可能な状態にコンパイルすることを考えます。

VSCodeでのコード補完を利用するためにthree.jsをnpmからインストールしたのでそのままでは実行できず、同じくnpmで提供されているツールであるwebpackというコマンドを利用します。

webpackコマンドをインストールする

プロジェクトのルートディレクトリから、webpackをnpmコマンドでインストールします。ブログとかには-gオプションをつけてグローバルにインストールする記述が多いが、グローバル空間はあまり汚したくないのでプロジェクト内に閉じることにします。
$ npm install webpack --save-dev
--save-devオプションをつけることで、webpackモジュールがインストールされると同時に、プロジェクトのpackage.jsonにあるdevDependenciesに記録されます。

これで、${PRJ_ROOT}/node_modules/.bin/webpackにコマンドがインストールされます。
$ node node_modules/.bin/webpack -v
2.5.0
みたいな感じになります。

webpack.config.jsを作成する

コマンドを直接
$ node node_modules/.bin/webpack  
のように使っても機能しますが、より簡単のために、webpack.config.jsという名前の設定ファイルを作成します。これがコマンドを実行するカレントディレクトリに存在することで、引数なしでwebpackコマンドを実行できるようになります。ここで、<entry>というのはブラウザでページを読み込んだときに最初に呼ばれるべきスクリプト(今回の場合はthree.jsをrequireしているほうのスクリプト)を指します。

以下に最低限と思われるentryとoutputだけ設定したwebpack.config.jsの例を記します。コンパイル元のJavaScriptファイルはsrcディレクトリ配下のindex.js、出力先はhtdocsのbundle.jsファイルとします。index.jsではthree.jsをrequireしているので、webpackを通してbundle.jsというファイルに統合されて出力してね、という設定です。 pathは出力先のoutput設定で絶対パスを要求されたので、それを解決するためのモジュールです。

const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'htdocs'),
        filename: 'bundle.js'
    }
};

上記がプロジェクトのディレクトリに存在すれば、webpackコマンドを実行するだけで、この設定に沿ったコンパイル処理が実行されます。これをindex.htmlから<script src="bundle.js"> のように呼び出せば、ブラウザからJavaScriptコードが実行される状態になります。

なお、上記の例では最終的にbundle.jsを呼び出すことになるHTMLファイルはあらかじめhtdocsファイルに静的なファイルとして存在していることとしています。調べてたところhtml-webpack-pluginというものが存在しているようですが、今回の例ではこれで十分とします。webpackはCSSファイルや各種リソースをまとめるものなので、必要に応じてこの設定ファイルは設定を追加していくことになるはずです。

package.jsonにコマンド(scripts)を追加する

ここまでの設定だと
$ node node_modules/.bin/webpack
のようにコマンドを実行する必要があり、あまりスマートではありません。これを回避するのに${PRJ_ROOT}/node_modules/.bin/ディレクトリにパスを通すのも、そもそもグローバル環境を汚したくなかったのに本末転倒であって、これをnpm環境で統一することにして、package.jsonのscriptsという項目を使ってnpmコマンドを追加します。該当部分のみ転載します。
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
  },
一つ目の"test"というのはデフォルトで入っていたものなので気にしないことにします。あとここのscriptsに書く際はすでにnode_modules/.bin/にパスが通っている状態だそうなので、webpackというコマンド名だけ書けば良いことになります。

package.jsonに上記の設定があれば、以下のようにして単純に、webpackによるJavaScriptのビルドを実行することが可能です。
$ npm run build
機能拡張にはnpmのものもあるようなので、必要であれば任意のショートカットを割り当ててさらに手軽に実行することが可能になると思います。 https://marketplace.visualstudio.com/items?itemName=fknop.vscode-npm

docker上でWebサーバをホストする

htdocsに出力されたJavaScriptファイルをテストするのに、HTMLファイルをローカルファイルとして開くとセキュリティ上の制限が出てきたり、うまく動作しないことがあります。ブラウザ上の設定でこの制限を解除することは可能ですが、より実際の想定に近い環境としてlocalhost上にWebサーバとしてnginxを動作させ、これに静的なファイル群をホストさせて動作確認することにします。これはdockerがすでにインストールされている前提で、以下のようにして実行可能です。
$ docker run -v `pwd`/htdocs:/usr/share/nginx/html:ro --rm -d -p 8080:80 nginx
これで、http://localhost:8080でhtdocs内のファイルの動作確認が可能になります。

2017年5月6日土曜日

VSCodeでThree.jsの開発環境を整える(1)

しばらく利用していなかったVisual Studio Codeをバージョンアップしてみたらすごく速く使いやすくなっていたので、すこし本格的に環境を構築して使ってみることにしました。VSCodeおよびnodeなどもこれまでごく基本的な利用しかしていないので、それらの知識のアップデートも兼ねます。

とりあえず、JavaScript(Three.js)の開発環境を構築することを目的にします。
  • VSCodeのIntelliSenseを利用したコード補完ができること
  • ChromeまたはFireFoxでブレークポイントを利用したデバッグが可能なこと
  • デバッグはdockerのコンテナ環境で構築すること
上記3点ができるようになることを目的として、
まずは任意の.jsプロジェクトでthree.jsのコード補完が可能になることを目指します。

新規プロジェクトフォルダを作成する

任意のフォルダ名でプロジェクトフォルダを作成して、その中にcdします。
$ mkdir myproject
$ cd myproject

npm環境を作成する

まず、nodeのパッケージマネージャであるnpmが利用するpackage.jsonというファイルを作成します。これは以下のコマンドを利用するとjsonファイルが作成されます。自力で作っても別にいいと思う。
$ npm init
実行すると幾つか質問されるので答えていくが、とりあえずは適当(空欄)でもいいはず。

Three.jsをnpmでインストールする 

npmレポジトリにthreeというパッケージが存在するので、これをnpmコマンドでインストールします。注意点として、VSCodeのIntelliSenseがJavaScriptの補完をするためにはTypeScriptの型定義ファイル(?)を利用し、これはnpmで管理されているようなメジャーなものならばレポジトリで公開されているもののようなのだが、これをVSCodeが利用できるようにするためにはpackage.jsonのdependenciesリストに対象のモジュールがリストされている必要がある(VSCodeは、ここにリストされているモジュール名をヒントにAutomatic Type Acquisitionという機能を使って型定義ファイルを自動で探しにいく。もしくはjsconfig.jsonというファイルに明示的に宣言することも可能だが、今回は省略する)
すなわち、以下のコマンドを経由してthreeモジュールをインストールする。
$ npm install three --save
--saveオプションを忘れるとpackage.jsonが更新されないので注意する。--saveオプションは指定したモジュールをインストールすると共に、package.jsonのdependenciesリストに追加する。

 動作確認

以上でIntelliSenseは有効な状態となります。自分のモジュールの場合はどうするのかとかは今後調べる必要があるが、たぶんTypeScriptとかで書けということなんだと思う。

main.jsとかの適当なファイルを作成して、
var THREE = require('three');
THREE.
ここまでタイプしてCtl+Spaceとかすると、THREEの中にあるモジュールが補完対象としてリストされるようになっているはず。もしくは、.をタイプした時点で出てくるはず。これで暗記しなくてよろしい。