零.为什么要定制?
把IDE这样庞大的黑盒掀开一角,妄图进行深度定制,看起来那可真蠢,写写插件不好吗?之所以这样做,主要有2个原因:
更高的灵活性:不受扩展机制限制,无论定制现有功能,还是扩展新功能,都是可实现的
更细的控制粒度:深度的二次开发能够做到细节完全可控,满足细粒度的定制需求
实际上,灵活性收益的多少取决于扩展机制的限制程度,如果插件机制是完全开放的,二次开发带来的灵活性提升就显得不那么必要了,例如Atom的扩展机制,几乎没什么限制,依靠插件机制完全可以造出来一个全新的IDE,比如Nuclide
控制粒度则侧重于可定制能力,例如主题风格、UI布局、语法扩展等等,二次开发能够支持定制那些插件机制不允许定制的部分,小到应用名称/图标,大到UI布局/交互操作
另一方面,从需求场景来看,专用的IDE有几个优势:
一站式工具:集成。葫芦小金刚的感觉,拥有其它7个娃的所有能力
沉浸式体验:衔接。把工具链有机组合起来,脚手架-语法提示-Lint检查-构建-预览-调试-打包一条龙服务
平台化建设:整合。应对工具零碎、不成体系的问题,促进工具体系建设
规范化开发:约束。写法的灵活性与车间流水线协作是矛盾的,统一的开发环境能够提供更强的约束力
这也是ReactNative、Weex、微信小程序、支付宝小程序等特殊场景要提供专用IDE的原因,其一希望开发起来更方便,体验更好;其二希望在一定程度上规范写法,统一风格
一.预期特性
一款可用的定制化IDE应该具备哪些能力:
基础功能:至少要具备主流前端IDE的大多数能力,要能满足码码的变态欲望
集成能力:要能集成现有的常用工具,包括规范检查、构建、预览、调试、API文档等
可扩展性:一方面应该有开放的插件生态支持、另一方面要能从容集成将来的新工具
其中,各个能力的地位分别是:
空间/发展 可扩展性
-------
种子/成长 集成能力
-------
水/生存 基础功能
集成能力和基础功能缺一不可,可扩展性是想象空间。因为没有种子一切都是空谈,没有水就会迅速失去生命力,有了种子和水之后,是草还是树取决于空间。发芽之后,水要持续不断地满足,所以基础功能才是赖以生存的根本(码的不爽,再怎么方便我也不用)
另外,基础功能有其特殊性,前端IDE的选择一直是个口味问题,重如IntelliJ IDEA/WebStorm,轻如Sublime Text/VS Code,快如NotePad/Vim,想要用一块糖果解决这个众口难调的事情几乎不太可能,所以基于开源IDE进行二次开发似乎成了唯一的选择,除非有个高可用的IDE Core包含绝大多数IDE基础功能,很遗憾,暂时还没有这种东西(Monaco比较接近了,但还差一些关键的东西,比如可扩展性)
二.成熟案例
定制化的IDE似乎突然之间就冒出来很多,例如:
对应选型方案如下:
名称 | 跨平台 | 基础功能 | 实现方案 |
---|---|---|---|
微信开发者工具 | NWjs | monaco-editor | NWjs手搓,IDE Core用Monaco |
支付宝小程序开发工具 | Electron | vscode editor | Electron手搓,IDE Core用扒来的VS Code editor部分 |
React Native IDE | Electron | Atom | Atom插件合集,IDE Core就用Atom |
最初用微信开发者工具搞过事情(见上不了线的小程序),那种码起来束手束脚的感觉很不舒服(怎么连个xx功能都没有啊),这就是上面提到的水(当然,因为没得选,他们不用考虑水的问题),经过这么久的迭代,在代码编辑、文件管理等方面似乎改进了不少,再没有深度体验
支付宝小程序可能同样考虑了水的问题,所以选择了从VS Code扒一个editor的方案,应该是费了一番功夫的
RN IDE就粗暴得多了,拿了一堆Atom package(插件)过来,堆出了强依赖Flow的IDE,还号称:
A unified developer experience for software development
实际情况是,项目不用Flow的话,连个跳转到定义都不支持
三.可选方案
可行方案无非两种:
手搓:找个IDE Core,集成进来
二次开发:找个IDE,扩展增强
技术上需要抉择的有3个关键点:
跨平台方案:NWjs或Electron
IDE Core:Monaco或其它
开源IDE:VS Code或Atom或其它
如果是基于开源IDE二次开发,只需要关心用哪个IDE,如果是手搓的方案,则需要选择跨平台方案和IDE Core
NWjs vs. Electron
背景
NWjs
Intel上海开源技术中心孵化的项目(最初叫node-webkit),允许在Node环境创建Webkit浏览器窗体。后来从Webkit切换到Chromium,并明确了Nodejs + Chromium开发桌面应用的发展方向
Electron
Github开发Atom时采用并开源的技术,与NWjs有些联系,但实现上差异很大(进程模型、Chromium集成方式等)
差异
相同点:
以前端技术栈开发桌面应用,都有成熟案例,例如钉钉(NWjs)、VS Code(Electron)
技术实现上都是Nodejs + Chromium
区别和限制:
平台支持:Electron不支持XP和Vista,NWjs支持
进程模型:NWjs是单进程模型,共享堆内存;Electron是多进程模型,靠管道IPC通信
源码保护:NWjs支持源码保护(把源码编译成V8快照),Electron不支持
自动更新:Electron内建支持,NWjs社区模块支持
开发体验:Electron文档比NWjs更优秀一些,受欢迎程度上Electron 55.6k star; NWjs 33.1k star
其中,比较重要的是平台支持与源码保护方面的差异
应用场景
选用NWjs的原因:
平台要求支持XP或Vista
看重单进程模型共享数据的便捷,多窗体共享状态更容易一些
同构方面的好处,NWjs自定义的部分相对Electron少一些,可复用更多的同构代码(维护一份代码,跑在桌面和Web环境)
很在意源码保护的场景,比如游戏内购
选用Electron的原因:
“纯”客户端应用,对web环境没有支持计划
看重多进程模型的安全性,进程隔离
社区活跃度更高,开发成本更低
Monaco
开源,且高可用的IDE Core似乎只有Monaco,但存在一些难以克服的问题:
TSX支持程度一般,不支持JSX语法高亮
没有成熟的插件生态,VS Code插件无法低成本迁移过来
JSX语法高亮有多难支持呢?
可以查看Does monaco support JSX ?,16年底的问题,现在(18年3月)还open着。因为是来自底层正则引擎的限制,无法从.tmLanguage
低成本地迁移过来,详细见Colorization Clarification
P.S.那么TSX是怎么支持的,不都差不多嘛?因为TypeScript也是MS自家维护的,不支持说不过去,没有足够的理由的话,没人会去做巨量的正则转换工作
扩展机制更重要的是生态,毕竟资源有限,我们需要“拥抱”开源,而Monaco恰恰缺少这个,见Integrate VS Code extensions in the Monaco editor
P.S.幸好微信小程序没有造出全新的东西(只是XML,CSS,JS),否则IDE团队可能会面临巨大的工作量
VS Code vs. Atom
开源IDE | 技术实现 | 维护者 | 受欢迎程度 | 插件生态 |
---|---|---|---|---|
Atom | Electron | Github | 43K star | 插件多,但不活跃 |
VS Code | Electron | Microsoft | 42.6K star | 插件多,且活跃 |
Brackets | Chrome Embedded Framework(在Chromium之上的定制化方案) | Adobe | 28.6K star | 插件多,且活跃 |
单从上面的对比来看,VS Code最具优势。但为什么RN要基于Atom扩展而不是VS Code呢?
因为,VS Code对扩展能力限制很大,比如:
定制UI自由度很低,仅能在一些不起眼的位置加个图标或者选项
插件进程隔离,插件运行在独立的进程环境,除了被注入的扩展API外,根本摸不着IDE主体,意味着没有API就做不了
而Atom恰恰相反,没有进程隔离,允许深度UI定制,插件API都是相对底层的,不像VS Code只提供高度封装的,从扩展成本来看,Atom相当有优势
P.S.Atom刚推出时,性能为人诟病,给大家留下了不太好的印象,但日常使用貌似也足够,没那么慢
四.抉择
决策树如下:
5种可行方案优缺点对比如下:
方案 | 简述 | 缺陷 | 优势 |
---|---|---|---|
A)基于VS Code二次开发 | VS Code插件开发 + 尽量小修改源码 | UI定制成本高 插件能力受到严格限制 UI定制型插件极少 |
插件市场活跃度高 代码编辑体验好 启动性能高,插件按需加载 容易扩展,如Vue或更新的前端生态产物支持 |
B)基于Atom做二次开发 | Atom插件开发 + 尽量小修改源码 | 核心API薄弱 插件能力不受限,质量没有保证 插件市场活跃度低,后期维护成本大 代码编辑体验略差 |
UI定制容易 插件能力不受限 UI定制型插件很多,前期开发快 容易扩展,如Vue或更新的前端生态产物支持 |
C)修改RN IDE | 纯Atom插件开发 | 强依赖TypeScript、Flow JSX支持度不高,增强成本低 启动性能略差 |
应用场景类似,实现细节都可借鉴,无技术风险 现成的UI/交互,不用专门投入 |
D)Monaco + N | VS Code IDE core + Electron开发 | 手动实现,稳定程度没有保障 不支持JSX,增强成本很高 TSX支持程度不高,增强成本很高 |
去中心,灵活性高 开发成本比ABC高 |
E)alm + N | VS Code IDE core增强 + Electron开发 | 手动实现,稳定程度没有保障 JSX支持程度不高,增强成本很高 |
去中心,灵活性高 开发成本比ABC高,比D低 |
综合来看,真正可行的只有A和B,进一步的选择就要考虑工作量与可用资源了:
排期/关键时间节点:项目时间跨度,以及Alpha、Beta时间点
人力/战斗力:几人参与,能否并行,以及战斗力是否达标
技术栈熟悉程度:上手后能否保证正常进度
实际工作量:工作量是否溢出
假设只有1人月,那么选B,没什么风险,因为B是大前期,能迅速出东西,但将面临后期打酱油的问题
如果有2人月,可以尝试选A,低风险,因为UI定制成本是个不确定因素,影响前期进度,可能导致Alpha等靠前的时间节点压力较大,但大后期有绝对的发展优势
五.经验
从0到1
把大象装进冰箱需要3步:
首先明确种子与水各是什么
接下来选一颗有想象空间的好种子
最后源源不断地供水
种子与水缺一不可,极端条件下,种子 > 水 > 空间
立足实践
过程中犯了2个错误:
因为一句话,临时调整方案。后果是3天白做 + 2天返工
任务分配不合理,合适的人没有去做合适的事情。后果是浪费2天调研 + 2天进度滞后
面对权威压力,不应该动摇理性的判断力,tell me why,我们摆事实讲道理。对战斗力的判断应该基于此刻事实,而不是以往经历,只有真真切切地面对问题时,真实的战斗力才会展现出来
这一套东西,NB在哪里?
切换视角
反向推动能力
他们的电脑上可是什么都没有
结果之外的东西,有些时候与结果本身一样重要
可以看一下白鹭的Wing编辑器, 也是基于VSCode的, 还算比较深度的定制了.
非常优秀的分析
非常赞的文章啊,最近也在搞定制IDE