💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 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" /> ~~~ 你可以在 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 文件内程序包的选项。 ![](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) 上找到他。*