您好,欢迎访问三七文档
当前位置:首页 > 办公文档 > 工作范文 > JavaScript代码热替换
JavaScript代码热替换题叶·我花了不少时间去学习JavaScript的代码热替换技术,上周把Webpack的结果录了一个视频,这周又把相同方案在Figwheel环境当中粗糙地实现了一遍,如果关注这方面的进展可以往细了看一看,只是我的代码都基于Cirru也许不方便入手.总之,对于热替换技术我积攒了很多的感想,可以凑一篇文章来笼统说一下.另外在知乎上补了一个问题,如果有兴趣挖历史的话可以一看:有过哪些代码热替换的技术?-编程语言.我接触编程挺晚,2009年冬天大致对HTMLPython有了点概念,到2012年知乎上膜拜了Haskell,渐渐开始摸到了现在的方向,并且关注新技术,旧的历史我恐怕不了解,等待高人挖出来.过去抢镜的前端代码热替换做前端开发,接触到热替换的需求挺多的,最初是在浏览器调试工具元素界面上直接修改CSS属性,或者直接替换掉JavaScript运行环境的变量.然后Chrome开始发力,在Workspace工具当中集成热替换功能,比如2013年IO大会上演示CSS文件直接编辑生效,并且后来通过SourceMap支持的了LESS和SASS等.同时JavaScript文件的热替换也在RemoteDebuggingProtocol当中支持,在Workspace中修改的函数会自动替换掉正在运行的代码当中.就我所看到的,ChromeDevTools团队牛人真是高歌猛进.基于Webkit调试工具的热替换功能后来还被发挥得更漂亮.LightTable原本是基于node-webkit开发的IDE(现在已经切换Electron了,也是Webkit),LightTable用于演示JavaScript开发的例子,当时就是打开了一个WebGL的调试页面,一边修改JavaScript,一边画布上的粒子组成的立方体在更新,同时不会破坏它的旋转状态.至少对于开发而言是垂涎的.另一个方向上也有人把RemoteDebuggingProtocol扒出来开发新的工具叫做Amok,于是你可以在浏览器外边普通的TextEditor当中用了.反过来也见过SublimeWebInspector这样的项目把整个调试工具搬进编辑器,有点疯狂.到了LightTable当然绕不过BretVictor大神的InventonPrinciple演讲了,在LightTable之前作者了若干篇博文都是和BretVictor大神的东西相关的,不细说了.后来大家都看到2014年WWDCSwift发布时演示的Playground,太多太多LightTable影子,然而我不了解Swift开发不晓得热替换在Swift当中能走到什么程度?JavaScript这边激发的项目项目还有Tangle,这是一个动态修改文档的类库,也蛮有意思.前面提到了SASS,也就是编译到CSS的语言,在浏览器当中实现了热替换,而编译到JavaScript的语言也同时在发展着,而且其中的替换也远远不是编译到JavaScript然后动态patch掉runtime那么直接,毕竟这仅仅是Webkit当中带的功能.专业的函数式语言比如Haskell和Clojure编译出的JavaScript普通人恐怕觉得还不如ASM.js来的像JavaScript.Elm靠的是纯函数代码,直接进行函数替换.Elm语言热替换的文章回溯到2013年九月,作者演示了一个网页游戏当中,修改代码角色跳跃轨迹动态修改的例子,两年多之前,那可是非常震撼的.后来Elm做得越来越细,时间旅行调试,智能提示编译错误,俨然甩开频繁刷新页面的我们很多年.ClojureScript也是编译到JavaScript的函数式语言,热替换实现得有点晚,Figwheel在大会上亮相的时间还在Webpack很久之后,只是后来能和Webpack的热替换抢抢风头,比如说在Unity的VR环境当中热替换代码编程,而且Figwheel也跟着ReactNative一起用ClojureScript在Android和iOS做热替换.我没研究细节实现,也说不上来,据说已经能做到一份Om代码,同时热替换Web,iOS,Android三个平台.它的角色和JSX也蛮像的,一方面提供语法做静态分析和提示编译错误,一方面生成JavaScript和VirtualDOM去对付Native平台的环境.跳出JavaScript来说,热替换大概是早已存在的技术,Erlang在1987年发布的,我不清楚支持的时间但是很早就是支持了代码的热替换,当然纠正一下,并不是说开发时热替换代码,而是部署OTP应用时不需要整个杀掉旧的服务,只需要逐步替换成新的进程就好了.Elixir建立在ErlangVM之上,自然也继承了这个特性.我不大了解其他语言在这方面,看到AndroidStudio有支持热替换的消息,具体不清楚.开发环境热替换代码对于延续C风格的静态类型语言来说并不容易,只是对于那些消耗性能的脚本语言来说有点意思,比如Lisp系语言(我主要接触Scheme和Clojure)随语言附带的REPL环境,当中可以动态加载代码,比如Clojure的REPL可以声明:reload参数重新加载namespace(Scheme方面以及CommonLisp方向倒是不清楚).而流行脚本语言中Node.js可以神奇地手动清除缓存重新加载代码,Python似乎也是类似,而RubyPry似乎也有不俗的效果.Smalltalk由于自带开发环境,倒是可以在运行时中编辑替换掉方法.而CommonLisp只是大概看过OpenGL上热替换的例子,而Lua游戏界面可能是基于Love,也有相似热替换的方案.花时间扒一下大概有不少.Webpack和React我记得Webpack热替换模块出名是在2014年下半年的样子,相对于以往的前端打包工具而言,Webpack很让人赞叹的一点是所有的模块资源被抽象成了module,从而在Webpack打包时所看到的是大量Module形成的Graph,而不是单纯的文件.在这个Graph当中,一个文件被修改,就是类似于一个更新事件,这个事件随着Module依赖关系一层层往上传递,一直到被捕获,或者传递到根节点引发一次页面刷新.实际上通过Webpack提供的API,很容易你就能插入捕捉事件的代码,进行Module的热替换.在这个前端项目被越码越大且没有二进制文件不成熟的背景之下,Webpack提供的热替换方案十分宝贵.我们在开发的单页面初次加载代码也许随着CPU性能,API网络瓶颈,DOM初始化因素,导致每一行代码修改都可能依赖数秒钟的界面重载和环境的重现,而在热替换的情况下加上固有的文件监听延时可能几秒就好了,成倍地压缩了时间改善着工作效率.更可贵的是ReactNative跟着把战火烧到了iOS和Android两个平台,导致许多小公司在开发跨平台应用时机灵地盘算着省掉一半多开发者的可能性.对于前端来说,Webpack的成功促使了browserify-hmr的出现,又多了一个热替换的方案.给react-hot-loader接班的大概是Redux方案,也就是Elm给的方案(也许很多游戏应用早就做了,只是我外行),就是限制在全局的可变状态,搭配尽可能不存储状态的渲染代码.前端的代码热替换主要是替换渲染的逻辑,打头阵的CSS替换甚至都不是JavaScript运行时中间需要对付的问题,随后是JavaScript函数本身的替换,后面VirtualDOM方案将可变状态的DOM做了抽象的封装促成了DOM结构能随着JavaScript数据做替换.Redux也开始替换到了数据更新所使用的代码.有点跑题,但是注意,热替换的不是数据,而是逻辑,或者说描述转换或者过程的函数.当一段代码被完全替换时,实际上不仅仅是代码,包括所有原先的代码造成的所有效果,都需要被清理掉,从函数式编程的思路来说函数的效果,一是返回结果,一是副作用也就是除了返回值之外的状态操作(比如往外部作用域赋值,比如写文件).其中函数返回结果,或者在外层函数被使用,或者被垃圾回收,不急着考虑.而副作用,两个对策,一个是Elm限制程序使用纯函数隔隔离作用,一是Webpackdispose方法你自己去写回滚副作用的代码.从而在新的代码加载时就像是跟全新环境一样执行.另一个问题是开发的代码产生的破坏性效果,比如Error对整个进程的杀伤力恐怕不是dispose里写点代码能控制牢的.也有一些办法,主要是静态分析,比如Elm模仿Haskell的ADT分析,JSX对语法和PropTypes的静态检查,ClojureScript基于GoogleClosureCompiler实现的静态分析,至少思路都一致,就是有问题的代码尽可能早一点察觉,根本不予执行.即便进程出问题了,重要的是核心的全局状态数据不能丢,总是有办法把整个运行时重新生成出来的.在这样的套路之下,函数式编程的纯函数和隔离状态,就大展身手了.毕竟没写一段代码,比如服务器上注册一个routerhandler,当它的代码被替换需要清除时,又需要手动调用server.removeListener去掉oldhandler然后注册newhandler,而且一个server有几十个路由,这种麻烦事情谁喜欢做,还不如一开始就采用纯函数的手段来得痛快,最终只要把更新的代码分成几大块,针对性得一起处理了就好了.而且在函数式语言的严格限制当中,副作用也是少之又少,需要担惊受怕的奇怪代码也可以放心一点.我不吐槽JavaScript转而吹捧Clojure,并不是后者一定更方便,但前者这种散漫多变实在让我不能放心托付.今天微博上说了,ClojureScript和Figwheel环境乍一操作起来,坑比起Webpack还要多一些,不深入说了,大致上Cirru语法倒没什么问题,而是惰性计算和atom的引用上有我这个新手不理解的地方.ClojureScript编译时相比JavaScript能检查命名空间,变量定义,参数个数,同时限制了可变数据使用也就避开了大部分旧代码副作用而能够直接进行替换(更像是Amok用RemoteDebuggingProtocol对JavaScript函数body代码进行替换那样),只是更丰富的数据类型和功能确实带来了难度.前面我用Webpack和Figwheel搭建的环境,一来是前端DOM渲染采用热替换,避免破坏Store和WebSocket的连接状态,二来是服务端数据更新采取了热替换,避免了Database(我直接用的内存)和WebSocket的状态被破坏.我采用的Cumulo方案前端数据几乎完全从后端同步,意外着如果我将Database独立于进程做一些持久化,即便重启进程也能恢复整个环境.至少验证了一套方案,大多数情况可以做到在添加新功能,增加对应数据处理逻辑,的过程当中不需要重启服务器或者刷新浏览器页面,局部替换代码就好了.若干年后本来我因为害怕打算只专心写写东西,然而看多了近些年的自频道对创业潮也开始绷起了神经.当人们在推动大量的年轻人去在互联网创业,国内出现像是雷军这样谋大局的企业家让小米快速膨胀,也出现我厂CEO这样的新秀的时候,给一个成功企业家配备的可不仅仅是几个程序员对吧,首先需要投入大量的码农写业务,其次投入大量的研究者想办法放大码农的技能压缩其数量.简单说,代码需求越来越大,单兵的产量也越来越高.环境就像是气球正在被吹大,想想看,气球吹大之后你我分别被映射到哪个位置?思绪有点乱,换个问法,你在写服务器,Java,报错,修改,编译,运行,几分钟过去了,然而别人用Go改了一分钟,几秒钟编译出结果了.或者你在写HTML,样式不对,快捷键换窗口,改一下代码,刷新页面,终于做完了界面,然而别人用Pixate直接生成了页面交互出来.然后主管过来问进度,又说为什么别人能做出来你做不出来,那你为什么不学?面对的现象差不多,帐怎么算是每个人不同的事情,心累.若干年前,事情简简单单,你从高考跌进社会,所见所得想做一些事情.就像BretVictor所说的那样,音乐家能演奏,美术师能作画,但设计师却,那就写代码呗.然而,告诉我La
本文标题:JavaScript代码热替换
链接地址:https://www.777doc.com/doc-2880399 .html