# 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 所示。
![](https://box.kancloud.cn/2016-01-08_568f4ae685c15.png)
图 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 用户不知道要使用哪个文件。
![](https://box.kancloud.cn/2016-01-08_568f4ae6b1415.png)
图 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" />
~~~
你可以在 Internet 上找到许多像这样操作的示例,并引用 /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 文件内程序包的选项。
![](https://box.kancloud.cn/2016-01-08_568f4ae6cc2bd.png)
图 6 Visual Studio 中的程序包选项
如图 7 所示,当你键入程序包名称后,IntelliSense 将为你提供匹配的程序包和版本,从而节省了使用命令行或 Web 查询的时间。当你对 bower.json 文件进行更改并保存后,程序包将在本地安装,而无需转到命令行。从文件的角度来看,这里没有特定于 Visual Studio 的内容。换句话说,来自任何 Web 项目的默认 bower.json 都可以运行。
![](https://box.kancloud.cn/2016-01-08_568f4ae6e90fe.png)
图 7 Visual Studio 中的 Bower IntelliSense
图 8 显示了解决方案资源管理器中来自 bower.json 的依赖项,指示 Bower 如何完全集成到你的 Web 项目和 Visual Studio 中。
![](https://box.kancloud.cn/2016-01-08_568f4ae71389c.png)
图 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# 中的一种分裂与合并表达式分析器
- 别让我打开话匣子 - 过时的东西
- 编者寄语 - 灾难链