Bower
bower 的缺点比较明显,最大的问题就是缺乏统一的构建机制。但有意思的是 Google 的 Polymer 选择了 bower 作为包管理器,因为 Polymer 是建立在两个还没在浏览器里普遍实现的东西上的:HTML Import 和 SPDY。HTML Import 让你可以把 HTML, CSS, JS 写在同一个 HTML 文件里作为一个组件或是模块,然后通过一行代码引入:
<link rel="import" href="my-component.html">
同时,在一个组件里也可以引入其他的组件,也可以直接引用远程服务器上的组件。某种程度上 HTML import 可以取代现在的组件模块机制。而 SPDY 是下一代的 http 协议,可以让浏览器只用一个服务器连接传输多个文件。换句话说即使你页面里有很多个 HTML import 也不会因为多次请求导致页面加载缓慢。在这两个东西存在的理想情况下,前端项目是完全可以不需要构建过程的。这是 Bower 长远来看的一个意义,但现阶段对大多数开发者而言,构建依然是一个必不可少的步骤。
Component
曾经作为 TJ 脑残粉的我是坚定的 component 使用者,但用了一段时间以后有几个比较重要的不爽之处:
- 每一个 component 都必须要在 component.json 中手动列出所有文件,每次更改项目结构或是重命名文件都很麻烦,我还为此写了个 grunt 插件专门自动做这个事情。
- component 只有一个 wiki page 列表,没有一个可搜索的中央数据库,模块的可发现度比较低。同时,github 仓库的星数是唯一的模块质量指标,而 npm 则有下载统计和被依赖数量这些更实在的数据。
- 模块发现度低带来的另一个问题就是不同作者的模块之间很少出现公用的依赖。虽然 Component 的依赖是扁平的,在实际使用别人的模块的时候依然会出现重复(同样的问题不同的实现),这就导致很多人宁可自己造轮子,自己依赖自己,只是把 Component 当个工具而不是平台用。
npm + Browserify
我这里想要指出,npm 其实是一个非常好的前端(对,没错,是前端)包管理方案,最主要的就是依靠 Browserify 这个神器。Browserify 最大的意义不是让你能在 npm 上发布前端的静态资源,而是实现前后端的代码共享。npm上有很多包是前后端通用的,比如我要找个现成的算法实现,什么 levenshtein distance 啊,perlin noise 啊,gaussian distribution 啊,A* 寻路啊,npm 上一搜一大把。常用的库如 jquery backbone 之类的,只要你想得到的基本上都有 npm 版本。需要什么直接 npm install 就可以用在浏览器端的项目里了,Component 和 Bower 在这方面跟 npm 完全没有可比性,spm 就更不提了。开发流程上来说也极其省心,项目用 CommonJS 写,不需要任何配置,给一个入口文件就行!还有一个官方工具 watchify,一行命令跑起,保存文件自动构建,连 grunt gulp 都不需要。
这个方案唯一的缺点,就是 npm 的树状依赖结构可能导致重复的模块和代码量的臃肿,需要跑一次 `npm dedupe` 来尽量压平依赖树。当然,实际情况中前端模块出现依赖同一模块的不兼容版本还是很少见的。