# Visual Studio - Bower: 用于 Web 開發的新型工具
作者?[Adam Tuliper](https://msdn.microsoft.com/zh-cn/magazine/mt149362?author=Adam+Tuliper)?| 2015 年 10 月
在很長很長的一段時間內,我們都生活在一個美麗的圍墻花園中。在這個受到保護的 Web 開發生態系統中,我們使用像 ASP.NET 和 Visual Studio 這樣復雜的尖端技術。把世界上的其余工具都視為相當差的技術。我們屬于帝國的一部分,如果你愿意,這里在很長的一段時間內都是一個相當好的地方。
然而隨著時間的流逝,開發區域性、工具、資源等等已變得分散甚至非常混亂。但是一些堅實可靠的技術在此期間出現,其中包括 Bootstrap、AngularJS、Git、jQuery、Grunt、Gulp 和 Bower,并且習慣于 Microsoft 生態系統的 Web 開發者能夠充分利用這些工具。
在本系列的第一篇文章中,我將簡要概述 Bower,它是主要面向(但不限于)前端 Web 開發的程序包管理器。在第二篇文章中,我將介紹 Grunt 和 Gulp,這兩個基于 JavaScript 的任務運行程序可用于執行各種各樣的任務,例如復制文件、縮小、串聯甚至是編譯。
Grunt、Gulp 和 Bower 是 Web 開發庫中的附加工具。與它們集成的工具內置于 Visual Studio 2015 中,而對于 Visual Studio 2012 和 2013 則通過外接程序提供。你仍需要安裝它們。
有些人可能想知道 Microsoft 是否讓你學習和使用更多工具。NuGet 不能足以處理程序包嗎?msbuild 不能足以作為生成工具嗎? 這兩個問題的答案都是“能”– 在很多但不是全部的方案中。而對于那些傳統工具無法滿足要求的情況來說,Grunt、Gulp 和 Bower 將可以提供幫助。在 Web 項目中,你可能希望只要 CSS 文件發生變更便立即編譯 Sass。或者你可能希望獲取最新的 Bootstrap 或 Angular 版本,而無需等待 Microsoft 的人員從其中創建 NuGet 程序包。你無法使用 NuGet 或 msbuild 完成任務。
NuGet 是一項出色的技術并且處于持續開發狀態,它受到 Visual Studio 的支持且緊密與其集成。繼續為你的項目使用它,尤其對于需要對你的 Visual Studio 解決方案進行更改的二進制文件和項目。然而,每當 jQuery 或 Bootstrap 的新版本推出時,必須要有人為它創建和發布 NuGet 程序包。但由于 Bower 可以使用語義版本,因此只要一個工具發布并在 GitHub 上標記后,Bower 就可以使用它;無需等待其他人將它打包在 NuGet 程序包中。
我要將 Node Package Manager (npm) 用于 Bower 安裝以及下一篇文章中的多個項目。由于 npm 不是作為獨立下載提供,只需從?[nodejs.org](http://nodejs.org/)?安裝 Node.js 即可。有關安裝和使用 npm 的詳細信息,請訪問 Microsoft Virtual Academy“程序包管理和自動執行工作流”頁面,網址為?[bit.ly/1EjRWMx](http://bit.ly/1EjRWMx)。
Bower 是通常用于前端 Web 開發的主要程序包管理器,可以說,它是唯一僅面向前端的程序包管理器解決方案。用于前端 Web 開發的大多數程序包(例如 Bootstrap、jQuery 和 AngularJS)可以使用 npm 或 Bower 安裝,但是在許多情況下,通過 Bower 進行依賴項管理可能更容易一些(盡管一些人可能并不同意)。
Bower 程序包與 NuGet 程序包不同,并不局限于單一源類型。一個 Bower 程序包可以是一個 Git 端點、文件系統上的一個文件夾、內容文件或壓縮文件的一個 URL 等等。Bower 與列出已發布程序包的程序包注冊表集成,但要安裝的程序包無需列在 Bower 中。
## 安裝和使用 Bower
Bower 通常從 Git 庫請求數據,因此你需要安裝 msysgit (msysgit.github.io) 并選擇從命令提示符運行的選項,如圖 1?所示。
?
圖 1 借助命令行支持安裝 msysgit
由于使用 npm 全局安裝 Bower,因此你可以在系統上的任意位置使用它。你只需要安裝一次 Bower 即可,而不用為每個項目安裝。
~~~
npm install -g bower
~~~
現在你可以開始使用 Bower 了。打開命令行并轉到項目根文件夾,然后使用以下格式將程序包安裝到項目中:
~~~
bower install <package name/url/zip/etc.> --save
~~~
例如,要安裝 jquery,只需輸入以下內容:
~~~
bower install jquery --save
~~~
前三個單詞的意義也許顯而易見,但 --save 可能需要一些說明。此參數將使某個條目寫入 bower.json 文件,用于說明你已安裝此程序包。(Bower 在默認情況下不會創建此文件;你需要告訴它要這樣做,稍后我將對此進行討論。) 默認情況下,Bower 安裝命令將在運行安裝命令的文件夾中創建一個 bower_components 文件夾;可以使用 Bower 配置文件 .bowerrc 自定義bower_components 文件夾名稱。
你會在圖 2?中注意到 jQuery 程序包安裝結果包含在超過所需的許多文件和文件夾中。我在項目中只需要 jQuery.js,但是在本例中我得到了整個 jQuery 源代碼樹。許多程序包安裝確實會提供整個源代碼樹,通常遠超用戶所需。這使得新的 Bower 用戶不知道要使用哪個文件。

圖 2 Bower 安裝整個 jQuery 源樹
某些項目將發布應用的打包版本,除去所有你不需要的額外文件。例如,用于 AngularJS 的 Bower 程序包是脫離 Angular 根目錄(位于 GitHub 上,網址為?[github.com/angular/bower-angular](http://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 文件中替代此默認值)。正如圖 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 尚未安裝,則只要 jQuery 程序包的最新版本至少為版本 1.6 ,它就會安裝到 /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 中的程序包,并將它確定為根程序包的項添加到依賴項部分。但是要注意,如果 jQuery UI 依賴于 jQuery,則 jQuery 不會通過此方法作為依賴項添加到文件中,因為當你安裝 jQuery UI 時已將它安裝。最好檢查這個生成的依賴項部分,從而確保你同意應列出哪些依賴項。
現在,你可以在命令行為項目初始化 Bower,通常在 Web 項目的根文件夾中。然后安裝依賴項。示例 bower.json 文件顯示在圖 5?中。
圖 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。如果你恰好從此應用創建 Bower 程序包,ignore 部分將排除指定文件。因為我要處理 Web 應用而不是創建我自己的 Bower 程序包,這并不適用。dependencies 和 devDependencies 部分包含應用程序將要使用的所有已安裝程序包;下一部分將對它們進行詳細介紹。
## 管理依賴項
你已了解到可以在 bower.json 文件中指定兩種不同類型的依賴項:dependencies 和 devDependencies。dependencies 部分中的項目在你調用時添加,例如 bower install jquery --save。這些是將在應用的生產中運行的程序包(例如 jQuery)。而另一方面,devDependencies 項是通常不進行生產的程序包,例如 angular-mocks 等 mock 框架或 less/sass 編譯器。這些項在你使用時添加,例如 bower install angular-mocks --save-dev 選項。這兩種依賴項類型只記錄在 bower.json 文件中,而不會影響你在應用程序的文件系統上使用這些文件的方式。例如,如果你要在 QA 環境中執行程序包還原,從理論上說,你不需要安裝 devDependencies。
要僅在 dependencies 部分中安裝所有依賴項,并且忽略 devDependencies 中的所有內容(例如在創建生產版本時),則只使用 bower install –production。
如果要查看應用程序使用的所有依賴項,可以運行 bower 列表,這將生成如下輸出:
~~~
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 新手會很快發現一些程序包中包含大量文件,而他們可能只需要一個文件。某些 Bower 程序包在 main 配置部分中列出了使用程序包所需的一個或多個文件。例如,在安裝 jQuery 時,它在程序包中具有大約 90 個文件。但是若要使用 jQuery,你只需要 jQuery.js,因此解決方法是查看 main,然后注意對于 jQuery,它只在 /dist 文件夾中列出單個文件:
~~~
{
? "name": "jquery",
? "version": "2.1.4",
? "main": "dist/jquery.js",
...
}
~~~
如果你在 /dist 文件夾中查找 jQuery,你還需要查找用于調試的 jQuery.min.js 及其相應的 .map 文件,盡管在 main 元素中列出它們并沒有意義,因為目的是讓 jQuery.js 或 jQuery.min.js 而不是兩者同時用于生產。
運行 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 文件會引用恰好在此文件夾之外的文件,如下所示:
~~~
<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" />
~~~
你可以在 Inter-net 上找到許多像這樣操作的示例,并引用 /bower_components 文件夾內的文件。這不是一個整潔的做法。我不建議這樣做,舉例來說,如果我只需要少量文件(它們應縮小并連接為甚至更少的文件),我并不想部署這樣的文件夾以及可能成百上千個文件進行生產。我將在下一篇文章中介紹關于 Grunt 和 Gulp 的新技術,但我現在將討論幾種可用技術的其中一種,以使用 bower--installer 模塊通過更好的方式取出這些 main 文件。
bower-installer 模塊會將所有 main 文件復制到指定的文件夾結構。首先,通過 npm install -g bower-installer 在計算機上全局安裝此模塊。
接下來,向 bower.json 文件添加一個部分,用于指定這些 main 文件應復制到什么位置:
~~~
"install": {
? "path": "lib"
},
~~~
在本例中,每個程序包的 main 文件將結束于 \lib 下的子文件夾,例如 lib\jquery-\jQuery.js、lib\angular\angular.js。
你可以在相當大的程度上自定義此過程。務必在?[bit.ly/1gwKBmZ](http://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 子文件中。例如,如果你使用了三個程序包,并且每一個都使用 jQuery,則需單獨安裝整個 jQuery 程序包三次。嵌套依賴項可以創建非常長的依賴項鏈。因此,npm 的 Windows 用戶幾乎可以確保在某一時刻會遇到可怕的路徑長度錯誤,例如: 目錄名稱 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 嵌套依賴項結構附帶造成的結果,盡管 npm 3 的 beta 版本已具有平展功能。我的目的不是勸說你只使用其中一個,因為你可以愉快地同時使用這兩個工具。
## Bower、ASP.NET 5 和 Visual Studio
Visual Studio 2015 具有對 Bower 和 npm 的內置支持,包括安裝程序包和 IntelliSense。Visual Studio 的先前版本可以獲取這相同的功能,方法是下載和安裝適用于 Visual Studio 的免費程序包 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.json 配置,以便 bower-installer 將依賴項復制到此文件夾(盡管全新的 ASP.NET 5 模板是使用 Gulp 將預置文件復制到其目標,我將在下一篇文章中介紹)。
NuGet 程序包仍然非常出色,在 ASP.NET 5 項目中毫無疑問地被大量使用并受到支持。附注一點,NuGet 設置位于 project.json 的 dependencies 部分,但顯示在 Visual Studio 中的引用下方。NuGet 程序包對于服務器端程序包(例如日志記錄和 MVC 支持)來說開箱即用。
## 總結
Bower 是一個出色的工具,可以輕松集成到前端工作流。它的 API 易于使用,并支持集成到 Visual Studio 中,你可以將它與 npm 和 NuGet 一起使用來同時管理前端和后端程序包。花一到兩個小時學習 Bower;你會發現這很值得。
* * *
Adam Tuliper?*是生活在陽光明媚的南加州的一位 Microsoft 資深技術傳播者。他是 Web 開發者、游戲開發者、Pluralsight 作者以及全面技術的愛好者。在 Twitter?[@AdamTuliper](http://twitter.com/@AdamTuliper)?或[adamt@microsoft.com](mailto:adamt@microsoft.com)?上找到他。*
- 介紹
- Microsoft Azure - Microsoft Azure - 大圖
- 崛起 - 新手成功的秘訣
- ASP.NET - 借助 OmniSharp 和 Yeoman 隨時隨地使用 ASP.NET 5
- 使用 C++ 進行 Windows 開發 - Visual C++ 2015 中的協同例程
- Visual Studio - Bower: 用于 Web 開發的新型工具
- 測試運行 - 使用 C# 實現線性判別分析
- 代碼分析 - 借助與 NuGet 集成的 Roslyn 代碼分析來生成和部署庫
- 孜孜不倦的程序員 - 如何成為 MEAN: 快速安裝
- Microsoft Band - 借助 Microsoft Band SDK 開發 Windows 10 應用程序
- C# - C# 中的一種分裂與合并表達式分析器
- 別讓我打開話匣子 - 過時的東西
- 編者寄語 - 災難鏈