October 2015
Volume 30 Number 10
Visual Studio - Bower: Web 開発用最新ツール
Adam Tuliper | October 2015
長い間、開発者は恵まれた環境で仕事をしてきました。このように保護が行き届いた閉鎖的な Web 開発エコシステムでは、ASP.NET や Visual Studio といった高度なテクノロジを使い、他の環境で使われているツールに目を向けることはほとんどありませんでした。いうなれば、帝国の臣民として、長い間恵まれた環境で暮らしてきました。
しかし、時間は流れ、開発の文化、ツール、リソースなどが断片化していき、混沌とした時代になってきました。それでも、こうした状況の変化の中から、Bootstrap、AngularJS、Git、jQuery、Grunt、Gulp、Bower など、非常に優秀かつ堅実なテクノロジが登場してきました。マイクロソフトのエコシステムに守られてきた Web 開発者もこうしたツールを活用する時代が来ています。
今回は 2 部構成の連載の第 1 部です。今回は、こうしたツールの中から Bower を取り上げます。Bower は、主にフロントエンド Web 開発を対象とするパッケージ マネージャーです。ただし、対象はこれに限定されません。第 2 部では Grunt と Gulp を取り上げる予定です。これらは、ファイルのコピー、縮小、連結、コンパイルなど、あらゆる種類のタスクの実行に使用可能な JavaScript ベースのタスク ランナーです。
Grunt、Gulp、および Bower は、Web 開発のツール群に新たに追加できるツールです。このようなツールを統合する機能は、Visual Studio 2015 に組み込まれていますが、Visual Studio 2012 と Visual Studio 2013 ではアドインとして利用できます。いずれにせよ、Grunt、Gulp、および Bower はインストールが必要です。
こうしたツールを統合できるようにしていることから、マイクロソフトが開発者に学習を促して、より多くのツールを使用するように求めているように思えるかもしれません。NuGet ではパッケージを適切に操作できないのでしょうか。MSBuild はビルド ツールとして不十分なのでしょうか。どちらの疑問の答えも、例外はあるものの、多くの場合に「はい」になります。従来のツールが不十分だと感じたら、Grunt、Gulp、および Bower が役立つ可能性があります。Web プロジェクトでは、CSS ファイルを変更すると、必ず SASS をコンパイルすることになります。あるいは、Bootstrap や Angular に対応する NuGet パッケージをマイクロソフトのだれかが提供するまで待たずに、Bootstrap や Angular の最新リリースを入手できるかもしれません。どちらも、NuGet や MSBuild では実現できません。
NuGet は優れたテクノロジであり、開発やサポートが続けられており、Visual Studio へ密接に統合されます。特に、Visual Studio のソリューションに変更を加える必要があるプロジェクト (特にバイナリとプロジェクト) の場合は、NuGet の使用を続けてください。ただし、新しいバージョンの jQuery や Bootstrap が登場するたびに、だれかが対応する NuGet パッケージを作成しなければなりません。ですが、Bower はセマンティックなバージョン管理を使用しているため、ツールがリリースされて GitHub にタグ付けされるとすぐに、Bower で使用可能になります。つまり、だれかが NuGet パッケージをリリースするのを待つ必要がありません。
第 2 部では、Bower のインストールといくつかの項目にノード パッケージ マネージャー (npm) を使用する予定です。npm 単独ではダウンロードできないため、nodejs.org (英語) から Node.js をインストールします。npm のインストールと使用に関する詳細については、Microsoft Virtual Academy の「パッケージ管理およびワークフローの自動化」(bit.ly/1EjRWMx、英語) を参照してください。
Bower は、一般的にフロントエンド Web 開発に使用する主要パッケージ マネージャーで、おそらく、唯一のフロントエンド専用パッケージ マネージャー ソリューションです。フロントエンド Web 開発で使用する Bootstrap、jQuery、AngularJS などのパッケージのほとんどは、npm や Bower を使用してインストールできますが、多くの場合、Bower を使用する方が依存関係の管理が少し簡単になります (反対意見もあります)。
Bower パッケージは、NuGet パッケージとは異なり、ソースの種類が 1 つに限定されません。Bower パッケージは、Git エンドポイント、ファイル システムのフォルダー、コンテンツ ファイルの URL、ZIP ファイルなど、さまざまな種類になり得ます。Bower は、公開済みのパッケージを一覧するパッケージ レジストリに統合されますが、Bower に一覧されていないパッケージをインストールすることもできます。
Bower のインストールと使用
Bower は通常 Git リポジトリから取り出すため、msysgit (msysgit.github.io) をインストールして、コマンド プロンプトから実行するオプションを選択する必要があります (図 1 参照)。
図 1 コマンドライン サポートを使用した msysgit のインストール
npm を使用して Bower をグローバルにインストールすると、システム上の任意の場所から使用できるようになります。Bower をインストールするのは 1 回だけで、プロジェクト単位にインストールする必要はありません。
npm install -g bower
これで、Bower の使用準備は完了です。コマンド ラインを開いてプロジェクト フォルダーのルートに移動し、以下の形式でプロジェクトにパッケージをインストールします。
bower install <package name/url/zip/etc.> --save
たとえば、jquery をインストールするには、以下のコマンドを入力します。
bower install jquery --save
最初の 3 つの単語は文字通りの意味なので、--save について説明します。このパラメーターによって、bower.json ファイルにエントリが書き込まれ、このパッケージをインストールしたことが記録されます (Bower の既定ではこのファイルが作成されないため、作成を指示する必要があります。方法については後ほど簡単に説明します)。既定では、Bower の install コマンドは、bower_components フォルダーを作成し、このフォルダーでコマンドを実行します。bower_components というフォルダー名は、Bower の構成ファイル (.bowerrc) を使用してカスタマイズできます。
jQuery パッケージをインストールすると、予想以上に多くのファイルとフォルダーが作成されます (図 2 参照)。プロジェクトで実際に必要なのは jQuery.js だけですが、今回は jQuery のソース コード ツリー全体を取得しています。多くのパッケージ インストールでは実際にソース ツリー全体を取得すると、想定よりも多くのファイルやフォルダーが作成されることになります。その結果、Bower を使い慣れていないユーザーは、どのファイルを使用するかわからなくなります。
図 2 Bower がインストールした jQuery ソース ツリー全体
プロジェクトによっては、余分なファイルをすべて取り除いてパッケージ化したアプリケーションのバージョンをリリースするものもあります。たとえば、AngularJS 用 Bower パッケージは、GitHub の Angular ルートから入手できるリポジトリです (github.com/angular/bower-angular、英語)。このパッケージをインストールする (bower install angular --save) と、HTML ページで参照する必要がある .js と .css だけを取得できます。
パッケージを検索するには、bower.io に移動するか、Visual Studio IntelliSense を使用するか (後ほど説明)、コマンド ラインで以下のように Bower パッケージのリポジトリを検索します。
bower search jquery
一度に複数のパッケージをインストールすることも可能です。その場合は、以下のようにインストールのスクリプトを記述します。
bower install jquery bootstrap-css angular
#or install a specific version of jquery ui
bower install jquery-ui#1.10.4
#install a github repository as a package
bower install https://github.com/SomeRepository/project.git
Bower は、インストールするパッケージのローカル キャッシュを作成します。今回使用した Windows 8 システムと Windows 10 システムでは、既定のキャッシュ フォルダーは、C:\Users\<名前>\AppData\Local\bower\cache\packages です (この既定の設定は、.bowerrc ファイルでオーバーライドすることができます)。list コマンドと clean コマンドを使用してキャッシュ済みのパッケージを管理できます (図 3 参照)。bower のインストールを実行すると、Bower は可能な限りこのローカル キャッシュから取り出そうとします。
図 3 Bower のローカル キャッシュの使用
#install jquery package for the first time
bower install jquery
#uninstall jquery package
bower uninstall jquery
#install from cache (ie works disconnected)
bower install jquery --offline
#show me the cache
bower cache list
#clean local cache
bower cache clean
#will fail, package no longer cached
bower install jquery --offline
他のパッケージに依存するパッケージの場合、Bower は必要な依存関係をファイル システムにインストールしようと試みます。Bower はフラットな依存関係ツリーを持ちます。つまり、必要な依存関係は、依存関係を必要とする特定のパッケージの下ではなく、/bower_components フォルダー直下にインストールされます。たとえば、jQuery UI 用の bower.json ファイルには、依存関係として「"jquery": ">=1.6"」がリストされます。つまり、それまでに jQuery をインストールしていなければ、バージョン 1.6 以上の最新 jQuery パッケージが /bower_components フォルダーにインストールされます。
パッケージの更新またはアンインストールは非常に簡単で、バージョンと依存関係のチェックが行われます。
#will update based on version rules in bower.json, ex. "jquery": "~2.1.3"
#specifies any patch like 2.1.4 is acceptable to update, but 2.2.0 is not
bower update jquery
#will remove folder and reference in bower.json, but will prompt first
#if other packages have a dependency on jquery
bower uninstall jquery
bower.json ファイル
この時点で /bower_components フォルダーを削除すると、アプリケーションにインストールされているパッケージやアプリケーションに必要なパッケージがわからなくなります。ソース コードをパッケージなしで別の開発者に提供したり、bower_components フォルダーがないビルド サーバーなどの別環境にソース コードを持ち込むと、対処できなくなります。NuGet に精通している方は、packages.config ファイルがない状態を想像してください。アプリケーションに bower.json ファイルを用意して、Bower がパッケージの依存関係やバージョンを追跡できるようにするのが理想ですが、これはオプションです。
bower.json ファイルを作成するには、プロジェクトのルートで bower init コマンドを実行し、画面の指示に従います (図 4 参照)。
図 4 bower.json ファイルの作成
C:\Users\Adam\Documents\WebApp> bower init
? name: MyWebApp
? version: 1.0.0
? description:
? main file:
? what types of modules does this package expose?
? keywords:
? authors: Adam Tuliper <adam.tuliper@gmail.com>
? license: MIT
? homepage:
? set currently installed components as dependencies? (Y/n) Y
? add commonly ignored files to ignore list? Yes
? would you like to mark this package as private which prevents it from being accidentally published to the registry? (y/N)
bower.json ファイルを作成しないで大量のパッケージをインストールした場合、または –save オプションを使用しないでこのようなパッケージをインストールした場合、bower init コマンドの実行時に、「set currently installed components as dependencies?」(現在インストールしているコンポーネントを依存関係として設定しますか) と表示されます。この問い掛けに了承すると、、Bower は /bower_components フォルダー内のパッケージを調べ、ルート パッケージになると判断されるパッケージを dependencies セクションに追加します。ただし、jQuery UI が jQuery に依存する場合、この方法を使用しても、jQuery は依存関係としてファイルに追加されません。それは、jQuery が jQuery UI のインストール時にインストールされるためです。生成された dependencies セクションを調べて、了承した依存関係がリストされていることを確認します。
これで、コマンド ラインからプロジェクト用に Bower を初期化できるようになります。初期化は通常 Web プロジェクトのルート フォルダーで行われます。次に、依存関係をインストールします。図 5 に、サンプルの bower.json ファイルを示します。
図 5 bower.json ファイルのサンプル
{
"name": "MyWebApp",
"version": "0.0.0",
"authors": [
"Adam Tuliper <adam.tuliper@anonymous>"
],
"license": "MIT",
"ignore": [
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"angular": "~1.4.3",
"bootstrap-css": "~3.3.4",
"jquery-ui": "~1.11.4"
},
"devDependencies": {
"angular-mocks": "~1.4.3"
}
}
}
最初のセクションには、プロジェクトとパッケージの全体情報が含まれています。他にも説明が必要なセクションとして、ignore、dependencies、devDependencies があります。ignore セクションは、このアプリケーションから Bower パッケージを作成する場合に除外するファイルを指定します。今回は Web アプリケーションを開発するため、独自の Bower パッケージは作成しません。そのため、今回は該当しません。dependencies セクションと devDependencies セクションには、インストール済みのすべてのパッケージのうちアプリケーションが使用するパッケージを指定します。詳細については、この後説明します。
依存関係の管理
bower.json ファイルでは、種類が異なる 2 つの依存関係 (dependencies と devDependencies) を指定できることがわかります。dependencies セクションの項目は、たとえば、bower install jquery --save コマンドを呼び出すと追加されます。ここに含まれるパッケージ (jQuery など) は、アプリケーションの運用時に実行されます。devDependencies の項目は、angular-mocks のようなモック フレームワークや less/sass コンパイラなど、通常運用環境には配置しないパッケージです。devDependencies のエントリは、たとえば、bower install angular-mocks --save-dev オプションを指定すると追加されます。この 2 種類の依存関係は bower.json ファイルに記載されるだけで、アプリケーションのファイル システムでこれらのファイルを使用する方法には影響しません。たとえば、QA 環境でパッケージの復元を実行するのであれば、理論的には devDependencies の項目をインストールする必要はありません。
たとえば、リリース ビルドを作成する場合など、dependencies セクションにあるすべての依存関係だけをインストールし、devDependencies セクションにある依存関係を無視するには、bower install –production コマンドを使用します。
アプリケーションが使用するすべての依存関係を表示する場合は、bower list コマンドを実行します。結果は、以下のような出力になります。
bower check-new Checking for new versions of the project dependencies..
MyWebApp#0.0.0 C:\Users\Adam\Documents\MyWebApp
├── angular#1.4.3 (1.4.4-build.4147+sha.bb281f8 available)
├─┬ angular-mocks#1.4.3 (1.4.4-build.4147+sha.bb281f8 available)
│ └── angular#1.4.3 (latest is 1.4.4-build.4147+sha.bb281f8)
├── bootstrap-css#3.3.4
├─┬ jquery-ui#1.11.4
│ └── jquery#2.1.4 (3.0.0-alpha1+compat available)
└── jquery1#2.1.4 (3.0.0-alpha1+compat available)
過剰な数のファイル
Bower の初心者は必要なファイルは 1 つだけと考えることがよくありますが、パッケージによっては大量のファイルが含まれていることがわかります。Bower パッケージによっては、main 構成セクションに、パッケージを使用するのに必要なファイルが 1 つ以上リストされているものもあります。たとえば、jQuery をインストールすると、パッケージには約 90 個のファイルが含まれます。しかし、jQuery を使用するのに必要なのは jQuery.js だけです。この解決策は、main 構成セクションの /dist フォルダーを確認することです。JQuery の場合、ここには 1 つのファイルだけがリストされています。
{
"name": "jquery",
"version": "2.1.4",
"main": "dist/jquery.js",
...
}
jQuery の /dist フォルダーには、jQuery.min.js ファイルとデバッグ用の .map ファイルが含まれていることがあります。運用環境では、jQuery.js ファイルまたは jQuery.min.js ファイルのいずれか (両方ではない) が使用されるため、main 要素にこれらのファイルをリストする意味はありません。
bower list --paths コマンドを実行すると、以下に示すように、インストール済みのパッケージごとにすべての main ファイルが返されます。
C:\Users\Adam\Documents\MyWeb> bower list --paths
angular: 'bower_components/angular/angular.js',
'bootstrap-css': [
'bower_components/bootstrap-css/css/bootstrap.min.css',
'bower_components/bootstrap-css/js/bootstrap.min.js'
],
jquery: 'bower_components/jquery/dist/jquery.js'
正しいファイルを main セクションに記述するのは、パッケージ作成者の役割です。
既定では、パッケージのファイルはすべて /bower_components サブフォルダーに配置されるため、開発者は HTML ファイルでは以下のように /bower_components サブフォルダー直下のファイルを参照することになると考えます。
<link rel="stylesheet" type="text/css"
href="/bower_components/bootstrap-css/css/bootstrap.min.css">
<script src="/bower_components/bootstrap-css/js/bootstrap.min.js" />
<script src="/bower_components/angular/angular.js" />
<script src="/bower_components/jquery/dist/jquery.js" />
インターネット上には、このように /bower_components フォルダー内のファイルを参照する例がたくさん見つかります。これは適切な方法ではなく、推奨されません。、縮小したごく少数のファイルと、連結したいくつかのファイルだけが必要な場合に、このようなフォルダーや、数百、数千にも及ぶファイルを運用環境に配置するわけにはいきません。ファイルの連結については Grunt と Gulp を取り上げる次回に説明する予定ですが、今回は、bower-installer モジュールを使用して、このような main ファイルを適切に取り出す方法を 1 つ紹介します。
bower-installer モジュールは、指定したフォルダー構造に main セクションのファイルをすべてコピーします。まず、npm install -g bower-installer を実行して、このモジュールをコンピューターのグローバルにインストールします。
次に、bower.json ファイルにセクションを 1 つ追加して、main セクションのファイルをコピーする場所を指定します。
"install": {
"path": "lib"
},
今回の場合、各パッケージの main セクションのファイルは、\lib のサブフォルダー (lib\jquery\jQuery.js、lib\angular\angular.js など) にコピーされます。
このプロセスは大幅にカスタマイズできます。パッケージのドキュメント (bit.ly/1gwKBmZ、英語) を参照してください。
最後に、必要に応じて bower-installer を実行して、出力フォルダーにファイルをコピーします。Gruntや Gulp を使用するなど、タスクを使用してこれらのファイルをコピーする方法もあります。フォルダーへの変更を監視することもできます。ただし、今回の方法は、迅速で、依存関係が最小限に抑えられ、他のワークフローを必要としないで実行できます。
ビルド サーバーとソース管理
ビルド サーバーに必要なパッケージをインストールするにはどうすればよいでしょう。つまり、開発するコードだけをソース管理し、他のパッケージは、ビルド サーバーにインストールする (Bower、NuGet など) か、ビルド サーバーでビルドする (Sass、Less、CoffeeScript など) シナリオです。すべてのバイナリやサード パーティーとの依存関係など、すべてをソース管理するシナリオもあれば、パッケージ マネージャーを利用して、ビルド環境にパッケージを復元するシナリオもあります。通常、Visual Studio プロジェクトを他の環境に移す場合、移行先のコンピューターでパッケージを復元するものと考えます。ソース管理に関連する Bower の一般的推奨事項は、すべてのサード パーティー製のコードをソース管理することです。ただし、リポジトリが大きくなる可能性を受け入れることができるか、パッケージ マネージャーを利用したくない場合に限ります。それ以外の場合は、/bower_components フォルダーのソース管理は行いません。
bower.json ファイルだけを使用してすべての依存関係をインストールし、main ファイルをコピーするには、単純に以下のコマンドを実行します。
#Will read bower.json and install referenced packages and their dependencies
bower install
#Optional - copy each packages main{} files into your predefined path
bower-installer
npm だけではダメな理由
npm だけを使用する開発者もいれば、Bower を選択する開発者も、両方を併用する開発者もいます。Bower パッケージのリポジトリにも npm パッケージのリポジトリにも多くのパッケージが含まれ、さまざまなケースで開発者のワークフローを容易にします。npm は、Node.js アプリだけでなく、クライアント側パッケージやサーバー側パッケージの管理にも適切に機能します。npm には、入れ子になった依存関係ツリーがあります。つまり、インストールするパッケージごとに、各パッケージの node_components サブフォルダーにすべての依存関係がインストールされます。たとえば、3 つのパッケージを使用し、各パッケージが jQuery を使用するとすると、合計 3 回個別に jQuery パッケージ全体をインストールすることになります。依存関係が入れ子になると、依存関係のチェーンが非常に長くなる可能性があります。そのため、Windows ユーザーが npm を使用すると、ほぼ間違いなく、どこかの時点でパスが恐ろしく長くなります。たとえば、ディレクトリ名が「C:\Users\Adam\.......\node_modules\somePackageA \node_modules\somePackageB\node_modules\insight\node_modules\inquirer\node_modules\readline2\node_modules\strip-ansi\node_modules\ansi-rege ...」のようになります。
これは依存関係の構造を入れ子にすることによって二次的に生じる問題です。ただし、npm 3 のベータ版ではこの構造がフラットになっています。今回の目的は、どちらか一方を推奨することではありません。どちらにも固有のメリットがあります。
Bower、ASP.NET 5、および Visual Studio
Visual Studio 2015 には、インストール パッケージや IntelliSense など、Bower と npm 向けのサポートが組み込まれています。以前のバージョンの Visual Studio では、無償の Visual Studio 向け Package IntelliSense 拡張機能をダウンロードしてインストールすることで、同じ機能を入手できます。図 6 は、bower.json ファイル内でパッケージを管理するために利用できるオプションの一部を示しています。
図 6 Visual Studio のパッケージ オプション
図 7 に示すように、パッケージ名を入力すると、IntelliSense が一致するパッケージやバージョンを表示し、コマンド ラインでの入力や Web 検索の手間を省きます。bower.json ファイルに変更を加えて保存すると、コマンド ラインに移動する必要なくパッケージがローカルに保存されます。ファイルの点では Visual Studio 固有のものはありません。つまり、任意の Web プロジェクトに既定の bower.json が存在します。
図 7 Visual Studio の Bower IntelliSense
図 8 は、ソリューション エクスプローラーに表示される bower.json の依存関係を示しています。Bower が Web プロジェクトと Visual Studio に完全に統合されているのがわかります。
図 8 ソリューション エクスプローラーでの Bower の依存関係
ASP.NET 5 ではプロジェクトの構造が新しくなります。既定ではプロジェクト フォルダー内のすべてのファイルがプロジェクトに含められます。ただし、Web プロジェクトの /wwwroot フォルダー内の項目だけは、静的コンテンツ (HTML、CSS、画像、JavaScript ファイルなど) としてアクセスできます。これを踏まえて、bower-installer モジュールが依存関係をこのフォルダーにコピーするように、bower.json 構成を設定します (ただし、ASP.NET 5 の既定のテンプレートは、Gulp を使用して目的の場所に事前設定されたファイルをコピーします。詳細は第 2 部で説明します)。
NuGet パッケージは依然効果が高く、ASP.NET 5 プロジェクトでも頻繁に使用され、サポートされます。ちなみに、NuGet の設定は project.json の dependencies セクションに配置されますが、Visual Studio では [参照設定] に表示されます。NuGet パッケージは、ログ記録や MVC サポートなど、サーバー側パッケージとしても使用されます。
まとめ
Bower は、フロントエンド ワークフローに簡単に統合できる優れたツールです。API は簡単に使用でき、Visual Studio に統合されます。Bower を npm や NuGet と併用すれば、フロントエンド パッケージもバックエンド パッケージも管理できるようになります。Bower の学習には 1 ~ 2 時間かかりますが、学習する価値はあります。
Adam Tuliper は、南カリフォルニア在住のマイクロソフトのシニア テクニカル エバンジェリストです。Web 開発者、ゲーム開発者、兼 Pluralsight の執筆者で、すべての技術に愛着を持っています。Twitter (@AdamTuliper、英語) で彼をフォローできます。連絡先は adamt@microsoft.com (英語のみ) です。
この記事のレビューに協力してくれたマイクロソフト技術スタッフの Michael Palermo に心より感謝いたします。