发布于 2017-08-03 07:49:18 | 113 次阅读 | 评论: 0 | 来源: 网友投递
Vue.js 轻量级 JavaScript 框架
Vue.js 是构建 Web 界面的 JavaScript 库,提供数据驱动的组件,还有简单灵活的 API,使得 MVVM 更简单。
本文转载自尤雨溪的知乎专栏 —— 回应『Angular有哪些地方比Vue更优秀?』。
最近 @大漠穷秋 发布了一篇对比 Angular 和 Vue 的文章。框架之间的对比虽然是老生常谈,但也确实是绕不过去的话题,Vue 本身的文档里也直接就有和其他框架的对比。同为开源的技术方案,比较本身其实没有任何问题,但在写 Vue 与其他框架的比较的时候,我们尽力做到两点:
确保事实的准确性。有的就是有,没有就是没有,不确定的就不说,弄错了一定改。
确保语气的中立性。别人的缺点指出但不嘲讽,优点大方承认。
之前 @汪志成 对 Vue 跟 Angular 的比较文案提出了意见,我们也对应地进行了修订。也欢迎社区继续进行监督和反馈 —— 比较的目的不是扭曲大家的认知,而是为了帮助大家做出自己的判断。
现在说回来大漠(后面都用大漠指代,注意跟 w3cplus @大漠 老师不是一个人,对不住了哈哈)的这篇文章,很遗憾,以上两点都不及格。
先说事实。
首先两个框架 CLI 的定位不一致。vue-cli 不是一个打包工具,它只是一个 scaffold,也就是初始化工具。真正负责打包的是初始化之后项目内的 webpack 配置和 npm 脚本。从一开始 vue-cli 就是这样的设计意图,项目真正的工具链在项目模板里面而不是 CLI 里面。
相比之下 @angular/cli 是一个全包式的命令行工具,一切都是通过 `ng` 来执行,但这不代表 `ng` 有的命令 Vue 就没有对应的功能 —— 比如在 vue-cli 生成的项目里面:
npm run dev 对应 ng serve
npm run build 对应 ng build
npm run lint 对应 ng lint
npm run unit 对应 ng test
npm run e2e 对应 ng e2e
除了 i18n 之外,@angular/cli 有的 Vue 都有。『很多日常开发必备的功能都需要开发者自己去下载配置第三方的Node模块』这句话是一个事实上的错误。看起来大漠连 vue-cli 生成的项目都没跑过就急着写文章了呢。
其次,CLI 命令/参数多 = 更优秀?并没有这样的道理,create-react-app 估计要哭晕在厕所了。如果我们仔细看看文中的截图,ng build 的多个参数,其实就是对应不同的底层 webpack 配置。说实话,我相信不仅仅是我,对于很多其他开发者而言,更宁可直接阅读 webpack 的文档来调整真正的 webpack 配置(并且可以 commit 进项目),而不是去额外学习一套由 Angular 封装的抽象,因为实际生产中需求千变万化,完全被 CLI 封装的配置不利于二次开发。
实事求是地说,@angular/cli 确实有一些值得学习的地方,比如 ng serve 对 SSL 的支持。我们也会在新版本的 vue-cli 中持续吸收改进,但连 vue-cli 能做什么都没弄清楚就拿玩具来打比方,只能贻笑大方了。
我不知道为什么大漠又截了个不知哪里的旧中文文档的图,还没截全 —— 最新的关于异步加载的文档是下面这两个链接:
Vue 将一个组件(以及其所有依赖)改为异步加载,所需要的只是把:
import Foo from './Foo.vue'
改成
const Foo = () => import('./Foo.vue')
就这么简单。这里注意三点:
当这样分割的时候,该组件所依赖的其他组件或其他模块都会自动被分割进对应的 chunk 里,不存在大漠所暗示的『手动改 500 个组件』这样的情况。况且两边代码分割的功能都是 webpack 提供的,我真不知道大漠是真的不懂还是故意误导。
所谓的路由级别的分割,只需要把这个组件作为路由组件就可以了,甚至连路由配置表都不用改。
更重要的是这样的异步组件并不一定只能用在路由层面 —— 任何你要用到一个组件的地方,都可以用异步组件无缝替换之,这种灵活性是 Angular 的 loadChildren 根本无法比拟的。比如一个动态的长表单页面,你甚至可以根据用户目前的输入来动态抓取表单接下来的部分(这个用例还是 wepback 的维护者 Sean Larkin 发现并用在生产中的)。
Vue的单元测试需要你自己去安装配置 Karma + Jasmine
—— 事实错误。vue-cli 的 webpack 模板内置了开箱即用的 Karma + Jasmine 配置,自带了一个初始测试用例,npm run unit 即可。这又双一次证明大漠根本没有跑过 vue-cli 生成的项目。
Vue 的单测不仅仅支持 Karam + Jasmine - 事实上社区有广泛的单测反馈,对于 Jest, Ava 都有实践,我们正在开发中的官方的单测工具库 vue-test-utils (由社区最流行的单测库 avoriaz 的开发者开发)会进一步简化常见的组件单测断言需求,并且还会有和所有主流 test runner 的整合指南。
在集成测试方面,Vue就只能是0分了,因为压根什么都没做。
—— again,事实错误。vue-cli 的 webpack 模板内置了开箱即用的 Nightwatch + Selenium E2E 测试配置,自带了一个初始测试用例,npm run e2e 即可。这又双叒一次证明大漠根本没有跑过 vue-cli 生成的项目。
从对集成测试的支持大家应该可以看出来,在那些技术含量不太高的地方,Vue确实可以抄袭得有模有样,但是一旦技术门槛提高,Vue就没法抄了,或者说抄得没那么快了。
—— 集成测试这种东西,有什么技术门槛可言,还需要抄么?顺便说一句,vue-cli 初始化的项目可是早比 @angular/cli 正式发布前就已经自带集成测试了...
原文直接说了说 TypeScript 有多好,言下之意这是只有 Angular 才有的东西?事实上:
Vue 全家桶自 2.0 发布起就自带官方 TypeScript typing;
Vue 有官方的 TypeScript component class decorator;
有非常多在生产环境中使用 Vue + TS 组合的用户;
VSCode + Vetur 插件提供完美的 IDE 类型提示;
TS 团队非常积极地和 Vue 合作推动更好的 Vue + TS 体验,下个版本的 Vue 甚至不需要用 class decorator 也能获得完善的类型推导。
这里我不否认 Angular 是一个 TS 为主导的框架,所以默认的 workflow 跟 TS 的整合会更紧密,但单说 TS 配置完成后的开发体验,并不构成本质的差别。
随着你的项目规模越来越大,你会越来越体会到有AOT是多么的重要,而Vue在这一点上根本无能为力,开发者只能自求多福了。
—— again,事实错误。Vue 从 2.0 一开始就对模板编译策略进行了专门的设计:框架本身的 dist 文件分为包含编译器和不包含编译器的版本,前者可以直接在浏览器里编译,后者则专门用于构建时 AOT 编译,并且剥去了编译器所占的尺寸。vue-cli 初始化的项目默认就是 AOT 的状态 —— 请注意,从 Vue 2.0 快一年前发布的时候就已经是这样了,早于 @angular/cli 支持 AOT 的时间。
Vue 在构建时还有很多其他优化,细节可以看我 7 月在 JSConf 演讲的末尾部分。
再说说 Treeshaking。上面的 slides 里面也有提到 Treeshaking 的原理,这里谈几点:
直到 webpack 3.3 之前,treeshaking 都依赖 rollup。框架本身层面,Vue 的 dist 文件就是用 rollup 打包的 flat ES module(注意,这又是一个 Vue 2.0 发布时就采用的设计,React 后来也采用了同样的构建,而 Igor Minar 提到过 Angular 也想采用同样的发布构建),保证了框架本身尺寸的最小化。
应用层面的 Treeshaking,@angular/cli 也是要用 rollup 才能达成,而 webpack 3.3 之后终于支持真正的 treeshaking(文档里叫 scope hoisting)—— 任意使用 webpack 的项目只要启用 ModuleConcatenationPlugin 就可以获得 类似 rollup treeshaking 的效果。对于 vue-cli 的模板来说,默认启用就是举手之劳,现阶段只是希望等这个功能更稳定一些。
我很早就说过了,用『一个人』来贬低一个项目是很短视的行为。Ruby 最早只有 Matz,Python 最早只有 Guido,Linux 最早只有 Linus,任何项目,尤其是独立开源项目,都有一个发展的过程。有爹如 Angular 1,下场又如何呢?
Vue 的 contributor graph 有一些细节,不说估计很容易就被忽略了。2.0 的代码在初始开发阶段只有我一个人写,所以绝大部分早期的 commit 都是我的,而且保留了所有细粒度的 commit,比如改个缩进啥的。到后期正式发布之后,commit 就开始强调可读性,一个 feature 一般都是 rebase 成几个比较阶段性的 commit,大部分 PR 也都是 squash 成了一个单独的 commit,所以 contributor 的 commit 会偏少。
还是用数据说话。如果只看近期的状态,这个网站有个指标挺有意思:最近的 100 个 commit 来自多少个 contributor?
Vue 是 23 个,Angular 是 38 个。Angular 更多,但很明显 Vue 也绝不是只有我一个人。
说了这么多,我们可以看到原文里几乎每一个技术比较点都经不起推敲,并且可以很明显的看出,作者对于 Vue 生态缺乏足够的了解,为了贬低而贬低的意图太过明显,甚至把一些在 Vue 当中更早落地的技术细节看做是在抄袭 Angular...
在我以前的一个回答中 (尤雨溪:什么才是你心目中的前端圈?) 我说过希望中文前端圈能少一些戾气,所以我这里尽量只谈技术上的事实,并且:
希望 Vue 的用户和支持者不要对大漠或 Angular 进行不理性的攻击。
希望 Vue 的用户和支持者不要对大漠或 Angular 进行不理性的攻击。
希望 Vue 的用户和支持者不要对大漠或 Angular 进行不理性的攻击。
重要的话说三遍。这篇文章不是为了撕逼,只是为了澄清一些技术上的事实。对自己要求更高一点的同学,可以不要站队。把自己跟一个框架捆绑不是什么好事,你的自信应该来自于你驾驭框架的能力,而不是被框架驾驭的能力。
大漠在另一个回答下面(知乎用户:为什么vue的高仿项目层出不穷,而React和angular却很少?) 也写过这样的一段话:
我曾经问过我的老板和Angular团队的负责人这样一个问题:在中国国内的网络上经常出现针对Angular的讨论,有一些内容非常偏激,甚至可以说【恶毒】,作为Angular在国内推广的负责人,我可以去和这些人针锋相对吗?我的老板是这样跟我说的:“战胜”竞争对手不是Angular团队的目标,我们的目标是帮助开发者和企业更好地开发面向未来的WEB应用。很平常的一句话,但是给我留下的印象非常深刻,因为我看到了一个全新的角度,原来他们是这样去思考问题的。反观国内的很多技术讨论区,很多情况下会非常快速地陷入人身攻击和胡扯的境地,给人的感觉就像泼妇骂街一样。尤其是前端社区,越来越像娱乐圈。所有的参与者,包括提问题的人,请你们安静一秒钟,仔细想想,你自己想要什么?在口水战中战胜对手能帮助你提高编码技巧,还是能帮助你提高认识世界的高度?
在那个充满戾气的问题下面看到这样一段话,当时我是很佩服大漠的。然而... 现在这两篇文章,真让我怀疑大漠是被人盗号了...
如果你没有被盗号,摸着你的良心问问,你,脸不脸红?
希望大家理性讨论。