ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

grunt-ts が .baseDir.ts ファイルを作るのを抑制する

Grunt を使っていて TypeScript のビルドを行うタスクを定義する際には grunt-ts を使うことが多いでしょう。 (grunt-typescript もあるけど。) grunt-ts で困ったことがあったので書いておきます。

outDir オプションを使うと .baseDir.ts ファイルが作られる問題

grunt-ts を使って tsc コマンドの --outDir オプション指定を行うには outDir プロパティが使えるのですが、この値を指定すると、何故か 「.baseDir.ts」 という名前のファイルがソースディレクトリの方に生成されてしまいます。

このファイルは何かというと、TypeScript 1.5 で --rootDir オプションが導入される前に grunt-ts 独自に --rootDir 相当のことをするために導入されたものです。 grunt-ts のドキュメントを読む限り、baseDir オプションを使っておらず、fast コンパイルが無効になっている場合には 「.baseDir.ts」 ファイルは作られないはずです。 しかしながら、grunt-ts 5.5.1 で試したところ、baseDir オプションを使わず fast オプションに "never" を指定しても outDir オプションを指定すると 「.baseDir.ts」 ファイルが作成されてしまいました。 個人的にはバグっぽいなーと思っています *1。 一応 pull request を投げておきました。

ちなみに以下のような Gruntfile.js (一部) で動作確認しました。

grunt.initConfig({
  ts: {
    default: {
      src: ["src/ts/**/*.ts"],
      outDir: "build/ts"
      options: {
        fast: "never"
      }
    }
  }
});

回避方法

現在 (バージョン 5.5.1) の grunt-ts に .baseDir.ts ファイルを作らせないようにする方法はいくつかあります。

outDir オプションではなく additionalFlags--outDir オプションを指定する

grunt-ts は outDir オプションを見て 「.baseDir.ts」 ファイルを生成するかどうか決めているので、additionalFlags の方で --outDir を指定すると 「.baseDir.ts」 ファイルは生成されません。

grunt.initConfig({
  ts: {
    default: {
      src: ["src/ts/**/*.ts"],
      options: {
        additionalFlags: "--outDir build/ts"
      }
    }
  }
});
tsconfig.json ファイルを指定する

tsconfig.json の中で outDir オプションを指定し、grunt-ts には tsconfig プロパティで tsconfig.json のパスを指定教えるだけにするという方法もあります。 ただし、普通に指定するだけでは tsconfig.json を解析して grunt-ts が余計なことをするっぽい (tsconfig.json 側で outDir オプションを指定していると、grunt-ts が .baseDir.ts ファイルを作ってしまう) ので、passThrough オプションを有効にして、grunt-ts が余計なことをしないようにする必要があります。

grunt.initConfig({
  ts: {
    default: {
      tsconfig: {
        tsconfig: "src/ts/tsconfig.json", // このファイルの中でコンパイル対象のファイル群や `outDir` 指定を行う
        passThrough: true
      }
    }
  }
});

おわり

こんなしょうもないことをやってるのは無駄だと思うし grunt-ts はオススメしません。

関連ページ

*1:ドキュメントの記述から察するに仕様ではなさそうだし、コードの実装も微妙に変なので

VirtualBox 5 上の Debian 8 に Guest Additions をインストールする

まあドキュメントを読めって話ではあります。 次のページにまとまっています。

背景

わりと長く VirtualBox を使ってきて、何度も Guest Additions をインストールしてきましたが、これまで Guest Additions のインストール手順をちゃんと見たことがありませんでした。

これまでは雑にインストールメディアからインストールできてたのですが、今回 VirtualBox 上の仮想マシンDebian 8 をセットアップして Guest Additions をインストールしたらちゃんとインストールできてなかった *1 ので、改めて調べてみました。

インストール方法

最初に言った通りドキュメントに全部書かれてますので、詳細はドキュメントを読んでください。

事前準備

まず、事前準備として、dkms パッケージをインストールします。 (Debian/Ubuntu 系の場合。)

apt-get update
apt-get install dkms

(root ユーザー以外で上記コマンドを実行する場合は sudo してください。)

んでもってシステムを再起動します。

インストール

再起動後、ゲスト OS が起動したら、まずは Guest Additions のインストールメディア (VBoxGuestAdditions.iso) を挿入します。 「デバイス」 メニューの 「Guest Additions CD イメージの挿入」 を選択すると、ゲスト OS にインストールメディアが (仮想的に) 挿入されます。

挿入された CD-ROM は /media/cdrom にマウントされます。 端末を開いて /media/cdrom に移動して、次のコマンドを実行することでインストールが開始されます。

sh ./VBoxLinuxAdditions.run

(root ユーザー以外で実行する場合は sudo しましょう。)

関連エントリ

VirtualBox で共有フォルダを使う

VirtualBox 上の Debian に Guest Additions をインストールする

dkms パッケージをインストールする以外の方法が紹介されてますが、まあ gccmakelinux-headers の正しいバージョンが入ればなんでも良さそうです。

*1:事前準備ができてなかった

実機の Android 端末に対して Hierarchy Viewer を使って View の階層構造を調べる

Android アプリを開発する際に便利な Hierarchy Viewer ですが、日本語のブログ記事だと実機の Android 端末に対して Hierarchy Viewer を使う際に ViewServer を使わない方法を紹介してるものがあまり見当たらない *1 ので、ViewServer を使わない方法を紹介しておきます。

Hierarchy Viewer とは

Hierarchy Viewer は、Android アプリの UI のデバッグや最適化を行う際に便利なツールです。レイアウトの View の階層構造を表示する機能 (Web 開発でいうところの DOM インスペクタみたいな感じ) や、ディスプレイの表示内容を拡大して表示する機能 (Pixel Perfect というツール) があります。

Hierarchy Viewer を使うための準備

上記ページに書いてあります。 Android 4.1 以降の端末であれば、次の 2 つのことをすれば良いようです。

  1. Android 端末の開発者向けオプションを有効にする
  2. 開発に使用している PC の環境変数 ANDROID_HVPROTO の値を ddm にする

ロックされている Android 4.1 未満の端末の場合は、ViewServer を使用することになります。 エミュレータのような非ロックの Android 4.1 未満の端末なら何もする必要はなさそうです。 (エミュレータは非ロックです。)

使い方

公式のドキュメントを読むのが一番良いと思うのでリンクをはっておきます。

下記ページにて、Hierarchy Viewer の起動 (Android Studio のメニューから起動する方法) から一通りの使用方法が説明されています。

また、Hierarchy Viewer のより細かな使い方や、Pixel Perfect の使い方などが以下のページで説明されています。

関連ページ

*1:「最近は ViewServer を使わなくてもできるらしいけど方法がわからなかった」 というような記述がみられる

*2:このエントリを書いた後に存在に気づきました。

UWP アプリ開発に TypeScript + React を導入することの検討 (Node.MSBuild.Npm の紹介)

こんにちは! 株式会社はてなにて、主に 「はてなブックマークAndroid アプリの開発を行っている id:nobuoka です。 この記事は、「はてなデベロッパーアドベントカレンダー 2015」 の 14 日目の記事です。 昨日は id:hatz48 による 「TypeScript だけで Web アプリケーションを作る」 でした。

今日は、昨日に引き続き TypeScript の話題となります。 主にクライアントサイド (特に UWP アプリ) での TypeScript と React の組み合わせについて検討したいと思います。

(この記事の内容は、UWP アプリへの導入を目的としたときの TypeScript + React の環境の一例であり、ベストプラクティスではありません。 より良い方法などがありましたら教えてくださいませ。)

UWP アプリと TypeScript + React

UWP アプリとは 「Universal Windows Platform アプリ」 のことで、Windows 10 で導入された Windows プラットフォーム向けのアプリの一種です。 Windows 8 で導入された Windows ストアアプリや Windows Phone 8.1 向けの Windows Phone アプリの進化版という感じですね。

現在のところ株式会社はてなでは UWP アプリの開発は行っていませんが、Windows ストアアプリ 「はてなブックマーク」 を 2012 年にリリースしています。 *1

JS を快適に書く : TypeScript の導入

Windows ストアアプリや Windows Phone アプリと同様に、UWP アプリも JS + HTML + CSS で開発することができます。 Windows ストアアプリ 「はてなブックマーク」 も JS + HTML + CSS の組み合わせで書かれています。

JS は Web 開発者にとって馴染みのある言語ですので、アプリ開発に取り掛かりやすいというのは利点ですね。 一方で、素の JS には変数に型がないためリファクタリングなどがしづらいという難があります *2。 それを解決するため、いわゆる Alt JS を使用することが検討されると思いますが、UWP アプリ開発で使用するのであればまず TypeScript が候補にあがるでしょう。 UWP アプリ開発に使用される統合開発環境 (IDE) Visual Studio 2015 では標準で TypeScript がサポートされているため、UWP アプリのプロジェクトに容易に TypeScript を導入できます。 Microsoft が TypeScript のリリースを行っているあたりも TypeScript 導入にあたっての安心感につながっています。 よほど TypeScript と比べて有利な言語があればそれを使うとよいかもしれませんが、私自身は現状では TypeScript を使うのが一番だと考えています。

実際に 「はてなブックマークWindows ストアアプリ *3 でも TypeScript を導入して開発しており、素の JS を使うのに比べて楽に開発を進めることができています。

View の処理を快適にするために : React の導入を検討

TypeScript を導入することで JS の変数に型付けが行われて IDE のサポートを受けやすくなり、JS の世界については快適になります。 しかしながら TypeScript を導入するだけでは view 操作 (「何らかのデータを画面に表示する」 という処理) の部分はあまり改善されません。 UWP アプリ開発のための JS のライブラリとして WinJS というものがあり、画面にデータを表示するためのテンプレート・バインディングの機能が提供されているのですが、これがなかなか素朴な仕様で、型の恩恵を受けづらいためです。

はてなブックマークWindows ストアアプリの開発でも、やはり View を扱う部分がきれいに書けず、よりよい方法を取り入れたいと考えています。

そこで、何らかのライブラリを導入することを検討しました。 候補としては、以下のものを考えました。 いずれも JS 界隈で話題になりやすいライブラリですね。

  • React
    • JSX 構文を使って JS 側に HTML 構造を記述する。
    • TypeScript との相性が良い。
    • アプリ開発をするうえで扱いやすそう。
  • Polymer
    • 標準の Web Components を意識して開発されており、将来性はあるように見える。
    • 独自の HTML タグを定義して HTML 側で使用できるので、(React と比べて) サーバーサイドで HTML を生成するような場面で扱いやすそう。
    • TypeScript との相性は不明。
  • AngularJS
    • 現在 Angular 2 が開発されており、バージョン 1 と 2 の互換性がなくなりそうなことから、現在 Angular を導入するのはリスキーだと考えられる。
    • View 部分を手軽に扱うためだけに導入するには規模が大きいように感じる。

全部試してみてどれが良いか評価できればよかったのですが、まずは TypeScript と相性がよく、アプリ開発で扱いやすそうな React だけを試してみました。

TypeScript と React (JSX) の相性

React では JSX 構文 (JSX syntax) を用いて JS の中に DOM 構造を記述します。 そして、TypeScript では JSX 構文がサポートされています。

JSX 構文での型チェックなどもサポートされているので、React を使うことで View の処理の部分でも IDE のサポートが受けられやすくなります。 プラグインなどではなく TypeScript の処理系に JSX 構文の処理が組み込まれているので、TypeScript と JSX の相性は非常に良いといえます。

TypeScript + React の環境

さて、ここからは実際に TypeScript + React を UWP アプリ開発で用いるための環境について考えます。 UWP アプリは、ローカルファイル上の HTML + JS + CSS をブラウザ上に表示するのと似たような仕組みで動きますので、まずはローカルファイルシステム上でビルドしてブラウザ上に表示できるようにする環境を考えます。

TypeScript + React の環境を整えるためには、npm を使用するのが簡単でしょう。

React を使うにあたっては CommonJS モジュールシステムを使うことが推奨されていますので、TypeScript を記述する際はモジュール形式で記述し、CommonJS 形式でコンパイルするようにしました。

We recommend using React with a CommonJS module system like browserify or webpack. Use the react and react-dom npm packages.

Getting Started | React

コンパイルした JS をブラウザ上で実行するために、また、UWP アプリの JS ファイルとして使用するためには、webpackBrowerify などを使用してパックしてやる必要があります。 今回は私は webpack を使用してみました。 (webpack を選択した理由は特にありません。 同僚からは、「webpack は大艦巨砲という感じなので、Browserify で事足りるなら Browserify で良さそう」 という意見をもらいました。)

これらのツールを使用して TypeScript + React のビルドを行うようにしたサンプルプロジェクトを GitHub で公開しています。 (ここではビルドシステムとして Gradle を使用しています。)

UWP アプリのプロジェクトへの TypeScript + React 開発環境の導入 : Node.MSBuild.Npm の紹介

さて、最後に UWP アプリのプロジェクトに上述の環境を構築することを考えましょう。

上で紹介した Gradle を使ったプロジェクトでは、Gradle から Node.js と npm を使用するために Gradle Plugin for Node を使用しています。 このプラグインは、ビルド時に Node.js と npm をダウンロードしてきて、セットアップしてくれるというものです。

一般的な UWP アプリのプロジェクトのビルドシステムである MSBuild でも同様の機能を使えれば、上で紹介したプロジェクトの Gradle 部分を MSBuild に置き換えることで、UWP アプリのプロジェクトに TypeScript + React の開発環境を導入できるでしょう。

MSBuild に似たような機能を提供する NuGet パッケージがないかどうか探したのですが、NuGet パッケージの中に node.exe や npm の各種ファイルを含むようなものは見つけられたものの、ビルド時にセットアップするタイプのものはなさそうでした *4。 そこで、そのような機能を持つ Node.MSBuild.Npm という NuGet パッケージを作成し、公開しました。

www.nuget.org

使用方法は簡単です。 まず、Visual Studio で NuGet パッケージマネージャを起動して 「Node.MSBuild.Npm」 を検索してインストールしてください。 あとは package.json を記述して、ビルド時に実行したい処理を build スクリプトとして package.json に定義するだけです。

例えば、TypeScript + React 環境を構築してビルド時に TypeScript のビルドや webpack による変換を実行するには、以下のように記述します。

{
  "name": "my-app",
  "private": true,
  "devDependencies": {
    "react": "^0.13.3",
    "webpack": "^1.12.9",
    "typescript": "^1.7.3",
    "dtsm": "^0.13.0"
  },
  "scripts": {
    "build": "dtsm install & tsc -p ts --outDir built\\typescript & webpack"
  },
  // 一部略
}

ビルド時に実行したい処理の記述方法に関しては、もう少し扱いやすいようにできると良いなぁと思っています。

ぜひご利用ください。

TypeScript + React 環境に対する評価

まだ軽く試している段階ですが、現時点での評価は以下のような感じで、個人的には他のライブラリ (Polymer や AngularJS) を試すまでもなく UWP アプリ開発に導入して良さそうという気がしています。

  • (良い) TypeScript が JSX をサポートしているので、JSX 構文内でも IDE のサポートを受けやすくて記述しやすい。
    • これは本当に便利です。
  • (良い) React 自体は大きなフレームワークではなく、導入がしやすい。
    • 画面内の一部の DOM 構造の構築のみに React を使用するなど。
  • (良い) React により View のコンポーネント化ができ、開発しやすくなる。
  • (良い) WinJS 側で React 用のアダプタが用意されており、WinJS と一緒に使いやすい。
  • (微妙) TypeScript + React の環境を作るのが少し面倒。 慣れれば問題はなさそう。
    • TypeScript をモジュールとして記述するかどうかや、モジュールとして記述する場合には browserify を使うか webpack を使うか、といったことで悩みそうです。 (React は CommonJS のモジュールシステムを使用することを推奨している。)
  • (不明、問題なさそう) 将来にわたってメンテナンスしやすいかどうか。
    • Facebook によりリリースされているので、ライブラリのメンテナンスの心配はそれほどなさそう。
    • 使い方次第ではあるが、React を使いながら徐々に別のライブラリに移行するというのも難しくはなさそう。

はてなブックマーク」 の Windows ストアアプリを更新する際には、こういった技術を導入することでより開発しやすく、メンテナンスしやすいコードを書けるようになりそうです。 *5

おわりに

はてなでは、より開発しやすく、よりメンテナンスしやすいコードを記述していこうとするエンジニアを募集しています!

hatenacorp.jp

明日の 「はてなデベロッパアドベントカレンダー 2015」 の担当は id:motemen です。 お楽しみに!

*1:以下 UWP アプリ向けの話をしますが、Windows ストアアプリでも基本的に同様です。

*2:UWP アプリに限らず

*3:UWP アプリではないですが、大体一緒です。

*4:NuGet パッケージ内に node.exe や npm を含むようなタイプでも悪くはないのですが、exe ファイルを複数プロジェクトで共有したかったり、プロジェクトの階層が深い場所にあると npm のパッケージのインストールに失敗するという問題があったりするので、ビルド時にホームディレクトリにインストールしてくれるタイプのものが欲しいのでした。

*5:この文は 「はてなブックマークWindows ストアアプリの大幅な更新を予告するものではありません。

発表資料: Android アプリ開発における Gradle ビルドシステム (京都 Android 勉強会 2014.08)

去る 8 月 23 日に株式会社はてな主催で行われた Android アプリ開発の勉強会 「京都 Android 勉強会 2014.08」 にて、Android アプリ開発と Gradle について喋ってきました。

Android Studio ではビルドシステムとして Gradle が採用されていますので、今後 Gradle を使う人は増えていくと思います。 Android Studio でビルドをするだけであればそれほど Gradle に詳しくなくても問題ないわけですが、せっかくなのでいろいろ便利に使っていきましょう、という主旨の発表でした。

発表内容は下のような感じで、Gradle を使ったことがない人にも 「Gradle でこういうことができる」 というのが伝わるように喋ったつもりです。 また、後半の方は Gradle を使って Android アプリのビルドをした人でも触ったことがない人もいると思いますので、Gradle を使っている人にも参考になったかもしれません。

  • Gradle と Android アプリのビルド
  • Gradle や Android Gradle plugin の機能の一部を紹介
    • ここら辺は知らなくても問題なく開発できるはずではあります
  • AAR パッケージについて
  • Gradle プラグインについて

勉強会では、Cookpad の @rejaspotaro さんが 「debug ビルドの時だけデバッグに便利なメニューを表示するようにしている」 とか、「社内でいくつか Gradle プラグインを作って便利に使っている」 という話を先にされていたので、そこら辺とからめて Gradle の話ができたのも良かったところです。

質疑内容

会場で 2 つほど (確か 2 つ) 質問がありましたので、ここにも書いておきます。

Gradle wrapper の更新

Gradle wrapper を使う場合、Gradle のバージョン更新はした方がよいのか、という質問でした。

Android Studio のバージョンアップにともなって必要な Gradle のバージョンも変わってきますので、Android Studio のバージョンアップに合わせてプロジェクト内の Gradle (Gradle wrapper) のバージョンも更新する必要があります。 最近の Android Studio では、Gradle のバージョンが古い場合に警告を出してくれて、GUI 上でぽちぽち操作すると自動的にバージョンが更新されるはずです。

Gradle の欠点

発表資料の中で 「Groovy のことを理解するまでデバッグ等が大変」 と書いていますが、それ以外に不便な点などはあるか、という質問でした。

Gradle 自身の欠点というわけではないですが、Eclipse での Android アプリのビルドと比べて、一部を変更してビルドし直すというのが Android Studio でのビルド (あるいは直接コマンドライン上で Gradle を使った場合のビルド) では時間がかかってしまうというのがあります。 私は今のところあまり細かい変更でビルドし直すということをしないようにすることでなんとかしていますが、UI の変更などでは細かく調整したいということもあってなかなか不便ということでした。

Gradle をオフラインモードにすると速くなるという話もあります。 (ちゃんと試してません。)