文 / 赋行
在即将到来的新财年之际,我想总结一下过去一年里我在前端领域的感受,借此总结反思过去一年里的成长,并展望新财年里的努力方向。
我的前身
曾经我是一名 Android 客户端开发,所从事的工作一直都是原生以及视频相关的内容,对于前端几乎没有接触,当初认为前端的工作过于简单并且一直都没有哪个前端技术能吸引到我,直到后来大前端的概念出现,才令我有了去涉足前端的念头;曾经客户端领域里如火如荼的插件化技术逐渐走向了衰落,连后来的 RN、Weex 都被 Flutter 和小程序逐渐替代,大前端领域的技术爆发式的增长,吸引我的已经不仅仅是某一项技术了,更多的是未来的技术趋势。在此之中,一个前端智能化的词亮在了我的眼前,利用机器学习来智能化生成代码,如此有意义的事情使得我最终加入了这个大家庭!
微弱的前端基础
回想起当初的编程之路,在大学的工作室里面看视频学习 J2EE,整体抱着一本《 Java 编程思想》来啃,虽然很苦逼,然而却很有意思,既然会 Java 后端开发,当然也懂前端,写后端的工作可谓是占用整个项目的大部分,当时前端在我眼里只不过是一个"页面仔",不外乎就是 HTML、JS、CSS,并没有多少的技术含量,我们花几天时间去W3School 学习一下就能掌握了。在学校做了不少的 JavaWeb 项目,并且学会了 JQuery、ExtJs 等等一些必备的前端技术,也就仅仅止步到此,没有再深入去了解前端领域了。
后来在客户端开发的工作中,接触到了 HyBrid,在 Native 层使用 Webview 来渲染 H5 页面,但是这更多的是了解了 JS 如何与 Native 通信的事情,依旧和前端接触不多。
用一张图总结我已有的前端基础知识便是:
转型之路
一年前,当我决定重回到前端领域的时候,蓦然发现,前端领域已经发生了翻天覆地的变化,即使平时我有去关注大前端的技术潮流趋势,然而只要我没有去深入接触开发,就不知道现在的前端已不再是当初那个"页面仔"所能驾驭的了。一下子需要学习的技术爆炸性性增长,我突然有了一种重回校园的感觉了,恨不得马上就开始学习起来,然而并不能盲目地去学习,否则就会陷入到前端的海洋里面去迷失方向;因此,需要有目标的去制定学习计划。
学习计划
关于前端的学习路线,网上有非常多的资料,然而这样大而全的学习路线,对我来说是非常混乱以及学习起来是非常耗时的,在大致了解过之后,我结合自身是客户端的情况,针对性的根据需求目标制定了相应的阶段计划,我的目标是需要在短时间内进入到前端领域,掌握其关键技术,然后融合到团队里面参与到业务需求开发中去(都怪产品提的需求太多了- -!):
- 第一阶段:重温网页三剑客基础,重温 HTML、CSS、JS 基础,以及学习全新(对我而言)的知识点,包括ES6、原型链、Flex 布局等等。
- 第二阶段:学习混合式的前端框架,HyBrid、RN、Weex、小程序、Flutter等等。
- 第三阶段:学习主流的前端框架以及项目构建管理,React、Vue、Angular、Webpack、NPM、Flux、Redux等等。
- 第四阶段:学习阿里内部的框架以及搭建技术,斑马、方舟、def、rax等等。
- 第五阶段:学习智能化领域的技术,机器学习、NLP、神经网络、TensorFlow、imgcook等等。
重启基础
由于我曾经有过相关 Web 开发基础,并不需要从零开始入门前端,因此我进需要通过 W3School 学习就回顾了已有的基础。然而这在实际应用开发上是远远不够的,特别是 JS,不会再使用 JQuery 来进行开发了,并且有原型链、箭头函数、类、Promise...至于更多新的知识点,我同事给我丢了一个 PDF (《深入理解ES6》)就开始看了,另外我还是结合了阮一峰的 ES6入门教程同步学习,边学变实践,很快就可以上手了。关于 CSS,最重要的还是Flex 布局,翻阅最多的还是阮一峰的文章:Flex 布局教程,实用性的技术一下子就掌握了,并且在后续的开发中不断查阅不断补充知识。
搭建环境
工欲善其事必先利其器,想要高效开发,必定需要一个顺手的 IDE (用vim、emacs、记事本开发的大神请跳过- -!)。想起在 Android 开发时有 Android Studio 等等各大神器的助力,前端也有 Visual Studio Code 这一大神器的鼎力相助,只要适当安装顺手的插件,开发起来甚是得心应手。
常用的插件如下:
- Prettier - Code formatter, Esben Petersen, 有了这个插件下面的配置才有用
- xtemplate - bakso,用于打开.xtpl文件
- vue - liuji-jim,用于打开vue的js文件
- IntelliJ IDEA Keybindings - 之前从Android或者后端转过来,习惯用IDEA的可以用这个插件,快捷键比较相似
- TabNine - 老外搞的一个自动补全插件,比较牛逼,但是我用起来也有点干扰
- Auto Import - ES6, TS, JSX, TSX, Sergey Korenuk, 只能提示import
- imgcook - 我们团队智能化产品插件,由设计稿一键智能生成代码的大厨,配合 VSCode 的强大工程能力,解放你的生产力。
曾经写Java 的时候,需要通过配置模板文件,然后在每次编辑以后格式化文件,要么就是在编写的时候遵循规范,然后现在写 JS,根本不需要关心这些了,只要我们使用同一份配置文件,编辑完代码在按下 Command+S 的时候就已经格式化好了,我使用的配置如下:
{
"editor.formatOnSave": true,
"typescript.preferences.quoteStyle": "single",
"javascript.preferences.quoteStyle": "single",
"prettier.singleQuote": true
}
混合式框架
如果只是学会了应用前端技术进行需求开发,那只不过是一个外包资源,并不能算一个高级前端工程师,所以我制定的第二个阶段计划是学习混合前端的开发框架,结合自身是客户端出身,对 HyBrid 有过一些了解,学习这些框架的原理还是比较容易的
我过去所在的客户端团队,所做的产品是面向双印的国际化产品,一些营销的活动需求,是前端开发的 H5 页面,根据实际的需要,我们并没有诸如 Weex、RN 和 Flutter 的框架,而使用的是最原始 HyBrid 框架,借助 JS Bridge 和 WebView 的能力开发,好处就是完全面向 Web 开发者,动态化能力好,劣势很明显的就是性能差。
Weex+Rax
第二代的跨平台技术无疑就是以 React Native、Weex 等等为代表了,虽然各大公司都有类似的框架,但是实际原理都差不多,掌握一款的原理即可。在阿里内部,当然就要学习 Weex 的原理了。
过去基于 HyBrid 框架开发 H5 页面,实际上开发的就是在浏览器运行的页面,只不过多了一个 JS Bridge 的能力罢了,可想而知,客户端里面的 WebView 就是一个浏览器,标准的实现难度非常高,引擎代码行数都在 500-1000 万行,历史悠久,包袱多,庞大的代码规模导致入门和改动成本比较高,加上渲染引擎设计的上的缺陷,如 JS Execute,Layout, Paint 都在 MainThread,无法并行化等等;因此无法实现客户端上的高级组件功能,如Recyclerview、ViewPager 等等。
第二代的基础架构如下:
这一代的技术就是抛掉了很多的历史包袱,重新实现了一个 JS Engine,通过 JS Framework 中间层,把前端的逻辑和视图转换成客户端侧的逻辑与视图进行渲染,最终通过前端代码完成了在端侧的渲染,实现更好的 Native 侧渲染体验。
优势很明显就是性能好了很多,而劣势就是无法完全兼容 Web 标准,只是一个子集,而且 Android 和 iOS 上存在差异。
Weex的架构如下:
Weex体系中 JS 的执行在 JS Thread,Layout 独立执行在 Layout Thread,渲染则在系统的 MainThread,三个线程相互独立,并行执行。在 WebView 的体系中 JS 的执行、Layout、Paint 都在 MainThread,相互影响,在进行复杂任务时会导致界面卡顿。然而,Layout 需要分别在 WeexCore 和 Android Native 本身的 Layout 中执行,效率不高,组件的封装成本随着复杂度增加也越来越高,难以逾越 Native View 限制提供更细致的 W3C 标准能力。
掌握了运行环境的原理以后,我便进入了学习前端开发框架以及项目构建管理这些实际应用的技术了,虽然 Weex 上层的 DSL 是 Vue 和 Rax,但是实际情况是我们已经不再使用 Vue 了(然而我还是学习了 Vue,可惜没有派上用场- -!),Rax 其实和 React 是一样,所以两者是互通的。会了这些还不够,还要了解一下 Webpack 的打包原理和 npm 打包。
而在阿里内部的话,主要就是摇学习了解 DEF 构建平台,根据定义,“DEF 是由淘宝前端团队发起的工程化前端开发生态体系。通过配套的规范、工具、流程定义、权限管理以及数据日志提高前端开发效率,保证团队开发过程的一致性和可复制性,提升代码质量和安全”。除了需要学习在 Weex 体系上开发前端页面,还需要学会开发大促会场的页面,那就是天马的搭建体系,诸如方舟、斑马的搭建系统。
D2C
到目前为止,规划里面的四阶段基本都达到了,剩下就是熟练的问题了,业务开发得再多,也不过是一个资深前端工程师罢了,并没有在一个垂直的领域里面扎根,也就是说深度不足,没有自己的抓手。
在我们团队,我们的使命是,释放前端工程师创新能力,为每一位工程师、设计师、产品提升效率,甚至释放双手,解放生产力,达到 0 研发的目标。D2C,说的是 Design to Code,通过AI和前端结合,实现前端智能化生产代码的伟大理想目标。
ImgCook
ImgCook 专注以 Sketch、PSD、静态图片等形式的视觉稿作为输入,通过智能化技术一键生成可维护的前端代码,包含视图代码、数据字段绑定、组件代码、部分业务逻辑代码等。
在我还没加入到这个大家庭之前,我们团队就已经孵化出了 ImgCook 这个产品,我并不能参与到这个产品的开发过程中,虽然感到很遗憾,却能享受到这个产品给我们带来研发效率提升的福利。
应用
通常我们的开发流程是产品提需求,然后出视觉稿,一般的视觉稿是以 Sketch 的形式给到研发同学,然后研发同学拿到视觉稿,就根据里面的内容来写界面,一点一点的来调 CSS 样式,有时候还需要自己去切图,好点的设计师会帮你切好图,并且上传到图片服务器,但是多数情况都是我们自己开发者才知道实际上需要什么切图,最终都是自己做了。当我们开发完以后,还需要设计师和业务老板进行走查,然后又是一波调整,这样来来回回折腾,实在是耗费了不少时间。
有了 ImgCook 以后,以上的问题可谓是迎刃而解啊,通过 ImgCook 来高度还原视觉代码,再也不用担心设计师调样式了:)下面我就以一个在项目中应用的实际开发例子讲一下我怎么使用 ImgCook 来为我日常开发提效的(在Mac 上使用 Sketch 来一键生成 Rax 代码)。
第一步:
需要准备好环境,我推荐去ImgCook官网上面阅读指导文档;在 Mac 上安装 Sketch,去 ImgCook 官网下载插件,然后双击 imgcook.sketchplugin 进行安装,安装成功以后效果如下:
第二步:
拿到设计师给的视觉稿,按照 ImgCook 官网上面的规范对其进行调整,当然,我们是强烈建议设计师在出设计稿的时候就遵循了 ImgCook 的规范。这些规范并不会影响视觉稿的效果,反而会使得 ImgCook 还原度更高。
我拿到的视觉稿如下,需要开发的模块如红色框框所示:
通常我们使用 ImgCook 是以模块为维度进行还原,因此需要把同一个模块里的图层编到同一个组里面,如下所示,编组的方法有两种,一个是按住 Command 建选择多个对象以后右键选择“编组选中对象”,第二方法是直接使用Command+G 的快捷键。
接着一个常见的调整就是切图,通常设计师会用多个元素对象组合成一个背景图,而我们只需要一张切图,这时候就需要对其进行合并操作了,首先使用以上的方法进行编组以后,点击 ImgCook 插件的合并按钮即可在编组名字生成了 #merge# 的标记,这样在导出的时候就会生成一张图片了:
有时候设计师出的图片尺寸过大怎么办?可以通过在编组里添加实际尺寸和位置的 Mask(蒙版)来解决,如上图所示的Mask就是一个蒙版。添加蒙版的方法很简单,实际上就是画了一个矩形然后置于这个编组的最底下即可。
实际效果,借助 ImgCook 官网的例子,如下,原图尺寸是 842 x 465,如果不加 Mask,生成的图片就不符合预期。Mask 的尺寸设置为 702 x 394,最后生成的尺寸就是期望的 702 x 394。
第三步:
调整好视觉稿以后,选择需要导出的模块编组,然后点击 ImgCook 插件面包的“导出数据”按钮即可导出数据:
导出成功以后有一个弹窗提示,点击去粘贴即可调整到 web 编辑器中,然后按下 Command+V 粘贴代码,就可以预览效果了,点击右上角的保存按钮进行项目保存,就可以查看生成的代码了。
第四步:
实际上 ImgCook 导出的是一个 json 文件,进行粘贴以后就可以预览,还可以在 web 上对其进行调整,效果如下,实际还有更多的牛逼的功能,如数据绑定,这就需要后端的接入标准数据模型等等,整体全链路的投入可以实现0 代码研发,具体可以参考我们团队的文章《双十一模块 79.34% 的代码是怎样智能生成的》。
点击右上角的代码即可预览生成的代码了,可以看到支持非常多的语言,还能添加自定义的DSL:
第五步:
最终把生成的代码 copy 到你的项目中即可(实际上这个 copy 操作挺没有必要的,虽然也可以安装一个 vscode 插件解决,但是出现迭代的时候依然不是一个有效的解决方案,这仅是一个低代码的方案,还不是无代码的实现)。
UI 与逻辑分离
前面借助了 ImgCook 生成了 UI 代码,这部分代码是没有业务逻辑的,纯UI展示以及交互动画等等的状态变更,因此需要一个有效的框架进行 UI 与逻辑数据的解耦,更加方便代码的管理。这里我借助客户端的经验,学习了前端的Flux 和 Redux 思想,简单实现了一个 UI 与数据逻辑的分离框架,如此一来,各个组件的功能内聚,不会耦合在一起,即使UI组件频繁调整更新也不会有影响:
- 组件设计,组件开发应该分为两层:
- 展示组件 View Component,这个是纯UI的组件,对外与用户产生交互,仅能通过 props 传递业务数据进行展示,通过 callback 进行反馈,不应该包含业务逻辑;独立支持可以由 imgcook 生成,或者让外包实现;
- 逻辑组件 Presentation Component,对外服务使用,与其他组件形成页面元素,内部负责获取数据,控制状态,然后通过 props 传递数据给UI组件。
- Action 设计,类型分为两种:
- 行为通信消息,方便组件间联动;
- 请求数据消息,逻辑组件使用,控制组件的状态显示。
- 逻辑组件尽量不用通过 props 来更新状态,应只有一个监听接口,由数据来驱动更新。
- 核心分发代码在 LogicManager 中实现;
- 通过 Typescript 来规范接口,通过注解实现。
#### PipCook
顺便广告一下我们团队的另外一个产品,这更多是偏向于后端算法工程的,因此我并没有使用经验,也没有去深入研究过。更多关于 pipcook,请查看 Pipcook Github。
PipCook 以“前端工程师 0 门槛应用机器学习能力”为使命,以“引领前端技术领域走向智能化”为愿景, 发展成为了从处理数据、训练模型到服务部署的一站式前端算法工程平台。Pipcook 将专注在前端领域,始终秉持着“站在前端工程师视角开发,对前端工程师友好”的原则,最终推动机器学习赋能前端行业向前发展。
加入我们
另外为我们团队打广告,如果你对我们的工作感兴趣,不管你是前端还是客户端都可以加入我们。
总结
在这一年里前端的技术我掌握了不少,已经能够满足岗位上的要求了,但是这还远远不够,前端的技术还有很多很多,我需要根据实际的需要去学习以及应用,才能创造出更大的价值。
未来的前端之路还有很长很长,结合了AI 以后,技术域更是扩展开了,需要学习的东西浩如烟海。不仅需要继续补齐前端的技术栈,还需要学习机器学习、NLP和神经网络等等的知识,日后进军到前端智能化的构建团队中去。