<link rel="import" href="my-component.html">
在倪云建的回答中,提到了Bower的一些缺点,其中最大的问题是缺乏统一的构建机制。然而,Google的Polymer选择了Bower作为包管理器,因为Polymer是建立在两个尚未在浏览器中广泛实现的技术上的:HTML Import和SPDY。HTML Import允许将HTML、CSS和JS写在同一个HTML文件中作为一个组件或模块,并通过一行代码进行引入:
同时,在一个组件中也可以引入其他组件,还可以直接引用远程服务器上的组件。在某种程度上,HTML Import可以替代现有的组件模块机制。而SPDY是下一代的HTTP协议,可以让浏览器只使用一个服务器连接来传输多个文件。换句话说,即使页面中有很多个HTML Import,也不会因为多次请求而导致页面加载缓慢。在这两个技术的理想情况下,前端项目完全可以不需要构建过程。这是Bower从长远来看的一个意义。然而,对于大多数开发者来说,构建仍然是一个必不可少的步骤。
Component曾经作为TJ的粉丝,我坚定地使用Component,但使用了一段时间后,发现了几个重要的问题:
- 每个Component都必须在component.json中手动列出所有文件,每次更改项目结构或重命名文件都很麻烦,我甚至为此编写了一个Grunt插件来自动处理这个问题。
- Component只有一个wiki页面列表,没有一个可搜索的中央数据库,模块的可发现性较低。同时,GitHub仓库的星数是唯一的模块质量指标,而npm则有下载统计和被依赖数量等更实际的数据。
- 模块的可发现性低导致不同作者的模块之间很少有公共依赖。尽管Component的依赖是扁平的,但在实际使用他人的模块时,仍然会出现重复的问题(相同的问题不同的实现),这导致许多人宁愿自己造轮子,自己依赖自己,将Component仅视为工具而非平台。
npm + Browserify
我想指出的是,npm实际上是一个非常好的前端(是的,前端)包管理方案,主要依靠Browserify这个神器。Browserify的最大意义不仅在于让你能够在npm上发布前端的静态资源,更重要的是实现了前后端代码的共享。npm上有许多前后端通用的包,例如我想找一个现成的算法实现,比如Levenshtein距离、Perlin噪声、高斯分布、A*寻路等等,npm上一搜就有很多。常用的库如jQuery、Backbone等,基本上你想要的都有npm版本。只需运行npm install,就可以在浏览器端的项目中使用它们,Component和Bower在这方面无法与npm相比,更不用提spm了。从开发流程的角度来看,这也非常省心,项目使用CommonJS编写,无需任何配置,只需要一个入口文件!还有一个官方工具watchify,一行命令就可以运行,保存文件后自动构建,甚至不需要使用grunt或gulp。
这种方案唯一的缺点是,npm的依赖树可能导致重复的模块和冗余的代码量,需要运行npm dedupe
来尽量压缩依赖树。当然,在实际情况中,前端模块出现依赖同一模块的不兼容版本是非常罕见的。