路由器Web页面(图示),主要负责路由器的配置管理,对于Web的学习算是从此起步。最近看着行业内日新月异的前端技术,谨纪录一下由此开始的前端之路。
一、路由器上的Web
路由器中Web场景的一些特征(合并了从产品/用研/工程角度的个人观点)
- 硬件设备性能/存储空间受限;WebServer需轻量(RAM有限)、页面资源要小(Flash有限)
- 用户端和服务器IP直连,链路上仅一跳;不用考虑Web资源部署、增量加载、流量优化等问题
- 单IP访问限制,同一时间仅一个登录态会话;不会有并发读写,Server端不用考虑识别用户(仅Admin账号,登录逻辑独立)
- 前后端数据交互简单,接口明确(很早就实践了API-First的策略:D)
- 页面跟随固件发布/更新,更新频率低(用户较少升级)
- 页面结构扁平(各模块的入口平级排列);且各模块相互独立(依赖清晰)
- UE/UX需求较弱;页面访问路径简单且集中
- 首次启用路由器,跟随引导页完成配置「☆☆☆☆☆」
- DHCP Clients查看,WAN接入配置更改「☆☆」
- QoS、防火墙等高级需求,网络故障排查「☆」
- 产品原型可以在立项初期明确、需求固化后很少变动
- 严格的瀑布开发工作流,不用考虑需求迭代
- 强调文档,且文档被较好维护(因此很多刚毕业的工程师可以很快投入项目)
同当今海量互联网服务所处的凶险环境相比,工程角度看、路由器Web开发活动只是”Hello World”级别的——本地随便起一个httpd托管webpages,”It works!”.
因此作为一个边缘的开发领域,早前的Web代码都是由嵌入式背景的工程师摸索完成的。(当时还是有不少创新的,比如为了解决ODM形态产品「快速替换页面文案」的需求而自研的i18n方案)
然而现在来看,早期的Web开发还是有不少反模式:
- 没有严格的前端代码规范:有驼峰命名也有下划线命名,很多inline JavaScript
- 没有模块划分概念;且一些跟随产品的差异需求,被hardCoded到前端逻辑里
- 各产品页面共用一套Codebase,没有版本发布管理的实践:巨大的一个 ***.js 文件塞满公共函数,服务着很多内外销产品及衍生产品,包括一些已经退市的产品
- 调试活动只能在板子上进行,很多页面是CGI吐出来的,小的修改往往也要对固件全量编译并烧机
- Web安全漏洞(http://www.routerpwn.com/)、一些预留的调试接口被打包发布
其实这些也不是什么重要的问题——
产品的竞争力不是体现于此、而是更多强调性价比上对竞品的绝对碾压——Web UI再友好易用、也只是个Shell而已;路由器的定位应该是像客厅的插排一样,配置完就躺在角落里了。
某种程度上,这也是正确且符合国情的——
就像对手机制造业的理解,”产品比iPhone有更好的信号、更大的电池”,999的期货价,自然能收割很大一部分市场。
正因为对于上游芯片厂商、下游分销渠道都有着的强大掌控力,对待创新时可以静观其变、利用资本和竞争壁垒的优势后发赶超。制造业寒冬到来前,一切看起来都还很不错。
二、重构之路
2013年,新的产品形态崛起(MiFi),即支持插SIM卡进行3G拨号、并提供Wi-Fi热点供附近的移动设备访问的便携路由器。一些其他的产品功能:
- 作为大容量移动电源
- 挂载SD卡作为移动存储设备
- 收发短信,如查询剩余流量
虽然有OLED显示屏分担了一些展示需求,但是毫无疑问Web的需求要多起来了、而且要更好支持移动设备的访问。产品质量压力开始凸显(各种移动端Bug和不友好体验),同时原页面架构和开发模式对于生产力的阻塞效应开始体现。
在一款TD方案的开发时,SoC厂商 *** 提供的SDK中,我们见识到了Ajax(13年,不要笑)、以及它是怎么做到前后端解耦的;随后开始对其他平台的Web方案进行类似的重构。同期在评估一款RTOS下的嵌入式WebServer时,从开源的Mongoose了解到了WebSockets及WebDAV,也通过WebDAV协议做了一个简单文件系统管理的方案。
这个过程中,因为原框架缺乏手脚架,导致新增模块的尝试步履维艰。
三、新WebUI
时间来到2014,智能路由的元年。
最早引起关注的是一款叫极路由的产品,漂亮的工艺、友好的使用体验、加上”极客”的自我标榜,迅速引爆了话题。虽然对于传统家用路由市场的冲击有限(当时智能路由在传统家用路由的市占率大概2%,媒体数据),提颠覆为时尚早、但确实带来不小压力。
对于开源的OpenWRT的研究以及LuCI WebUI的研究都正式立项,Web体验的强化和页面改版也提上日程,当时的直线Leader和Manager给予了很多支持。
注意到这个时候,已经不是再归咎Costdown思路的时候了,市场都看清了路由器作为流量入口和中枢这么一个巨大战略优势,传统厂商也投入了巨大资源进行研发。
…
既然新项目启动,是时候首先解决此前的技术债务和开发模式上的问题了。
- 制定代码规范,并通过JSHint进行静态代码扫描
- 代码分库,将webpages代码独立版本管理,配合Git钩子(hooks)和既有Gerrit CR工作流,强化提交质量和协同开发效率
- 通过Grunt来实现前端代码的模版替换、压缩合并、构建打包等,引入工具链代替此前的粗放模式
- 内网一台Linux服务器上部署了一台Web模拟器,模拟真机调试
- 实现了一套模块化加载的框架
- Wiki上持续汇报工作情况
所谓模拟器只是个Apache(非路由器上WebServer x86编译,彼时团队已经聚焦在前端了),主要是仿真所有的Web请求,包含一个Python WSGI后端(以Mock动态请求响应),一个MongoDB来模拟配置参数持久化。 服务器定义一个cron job,定期同步webpages库上相关分支的代码,同时还原DB中的数据(以重置模拟器上被修改的配置参数)。
当时只是为了解决webpages调试问题,现在回想应该可以作为一个工程创新:
- 同版本管理联动,自动部署最新代码(朴素的持续集成实现)
- 因为服务器内网全员可见,可以请同事定期访问体验(预发布的效果)
- 开发活动依赖兄弟部门的配合(UI设计、文案撰写、多语言文档翻译、测试用例设计),以往的工作流是要移交真机或开发板;现在完全可以直接通过浏览器访问模拟器进行
- 测试活动彻底解耦;通过修改UA来测移动版页面
整个过程都是摸着石头过河,比如想做模拟器时只知道CGI、不清楚可用一些Web框架来提高生产力;DB化的尝试用了MongoDB这么个有门槛的方案;了解到Grunt时对NodeJS和它的包管理系统懵懵懂懂、只是忠实地在文档中记录了要npm install
,等等。
四、Web技术小组
现在回想,如果当时有高手能指点一下方向或给一些总结,不仅能减少很多试错成本,还能让大家对于「所用之术」有了深刻「理解」、并转化为「知识」。就像武林之人只习得练武口诀、不懂心法,则技艺不精一样。
「尝试」=>「理解」=>「知识」=>「习惯」
这是一条连贯的学习链条,虽然很多时候「尝试」后就能贡献生产力了(换句话说,能技术变现了——做项目、就业,等等),但是在极度膨胀的领域知识下,技能也在飞速贬值;参考CPI和积蓄之间的关系,如何沉淀技术也是一个问题。
14年成立了技术小组,开始担任Web小组的Tech Lead.
最早是为了解决各个项目下技术方向发散的困境,也就是怎么沉淀技术。后面通过技术专题学习,组织现场代码走读等,有了一点收获;职业生涯中的第一次技术管理实践。
…
先写到这儿吧,发现全文更合适的标题是:《Web开发狗的产品经理心》