JavaScript代码热替换

上传人:飞*** 文档编号:50961173 上传时间:2018-08-11 格式:PDF 页数:5 大小:12.47KB
返回 下载 相关 举报
JavaScript代码热替换_第1页
第1页 / 共5页
JavaScript代码热替换_第2页
第2页 / 共5页
JavaScript代码热替换_第3页
第3页 / 共5页
JavaScript代码热替换_第4页
第4页 / 共5页
JavaScript代码热替换_第5页
第5页 / 共5页
亲,该文档总共5页,全部预览完了,如果喜欢就下载吧!
资源描述

《JavaScript代码热替换》由会员分享,可在线阅读,更多相关《JavaScript代码热替换(5页珍藏版)》请在金锄头文库上搜索。

1、JavaScript 代码热替换题叶我花了不少时间去学习JavaScript 的代码热替换技术 , 上周把 Webpack 的结果录了一个视频, 这周又把相同方案 在 Figwheel 环境当中粗糙地实现了一遍, 如果关注这方面的进展可以往细了看一看 , 只是我的 代码都基于 Cirru 也许不方便入手 . 总之, 对于热替换技术我积攒了很多的感想 , 可以凑一篇文章来笼统说一下. 另外在知乎上补了一个问题, 如果有兴趣挖历史的话可以一看: 有过哪些代码热替换的技术? - 编程语言 . 我接触编程挺晚 , 2009 年冬天大致对HTML Python 有了点概念 , 到 2012 年知乎上膜拜

2、了Haskell, 渐渐开始摸到了现在的方向, 并且关注新技术 , 旧的历史我恐怕不了解 , 等待高人挖出来 .过去抢镜的前端代码热替换做前端开发 , 接触到热替换的需求挺多的, 最初是在浏览器调试工具元素界面上直接修改 CSS 属性, 或者直接替换掉JavaScript 运行环境的变量 . 然后 Chrome 开始发力 , 在Workspace 工具当中集成热替换功能 , 比如 2013 年 IO 大会上演示 CSS 文件直接编辑生效 , 并且后来通过Source Map 支持的了 LESS 和 SASS 等. 同时 JavaScript 文件的热替换也在Remote Debugging P

3、rotocol 当中支持 , 在 Workspace 中修改的函数会自动替换掉正在运行的代码当中 . 就我所看到的 , Chrome DevTools 团队牛人真是高歌猛进 . 基于 Webkit 调试工具的热替换功能后来还被发挥得更漂亮. LightTable 原本是基于 node-webkit 开发的 IDE(现在已经切换Electron 了, 也是 Webkit), LightTable 用于演示JavaScript 开发的例子 , 当时就是打开了一个WebGL 的调试页面 , 一边修改 JavaScript, 一边画布上的粒子组成的立方体在更新, 同时不会破坏它的旋转状态. 至少对于开

4、发而言是垂涎的. 另一个方向上也有人把Remote Debugging Protocol 扒出来开发新的工具叫做Amok, 于是你可以在浏览器外边普通的Text Editor 当中用了 . 反过来也见过 Sublime Web Inspector这样的项目把整个调试工具搬进编辑器, 有点疯狂 . 到了 LightTable 当然绕不过 Bret Victor 大神的 Invent on Principle 演讲了 , 在LightTable 之前作者了若干篇博文都是和Bret Victor 大神的东西相关的 , 不细说了 . 后来大家都看到 2014 年 WWDC Swift 发布时演示的Pl

5、ayground, 太多太多 LightTable 影子, 然而我不了解 Swift 开发不晓得热替换在Swift 当中能走到什么程度 ? JavaScript 这边激发的项目项目还有 Tangle , 这是一个动态修改文档的类库, 也蛮有意思 .前面提到了 SASS, 也就是编译到CSS 的语言 , 在浏览器当中实现了热替换, 而编译到 JavaScript 的语言也同时在发展着 , 而且其中的替换也远远不是编译到JavaScript 然后动态 patch 掉 runtime 那么直接 , 毕竟这仅仅是Webkit 当中带的功能 . 专业的函数式语言比如Haskell 和 Clojure 编

6、译出的 JavaScript 普通人恐怕觉得还不如ASM.js 来的像 JavaScript. Elm 靠的是纯函数代码 , 直接进行函数替换 . Elm 语言热替换的文章回溯到2013 年九月 , 作者演示了一个网页游戏当中, 修改代码角色跳跃轨迹动态修改的例子, 两年多之前 , 那可是非常震撼的 . 后来 Elm 做得越来越细 , 时间旅行调试 , 智能提示编译错误 , 俨然甩开频繁刷新页面的我们很多年 .ClojureScript 也是编译到 JavaScript 的函数式语言 , 热替换实现得有点晚 , Figwheel 在大会上亮相的时间还在Webpack 很久之后 , 只是后来能和

7、Webpack 的热替换抢抢风头 , 比如说在 Unity 的 VR 环境当中热替换代码编程 , 而且 Figwheel 也跟着 React Native 一起用 ClojureScript 在 Android 和 iOS 做热替换 . 我没研究细节实现 , 也说不上来 , 据说已经能做到 一份 Om 代码, 同时热替换 Web, iOS, Android 三个平台 . 它的角色和 JSX 也蛮像的 , 一方面提供语法做静态分析和提示编译错误, 一方面生成 JavaScript 和 Virtual DOM 去对付 Native 平台的环境 .跳出 JavaScript 来说, 热替换大概是早已

8、存在的技术, Erlang 在 1987 年发布的 , 我不清楚支持的时间但是很早就是支持了代码的热替换, 当然纠正一下 , 并不是说开发时热替换代码 , 而是部署 OTP 应用时不需要整个杀掉旧的服务, 只需要逐步替换成新的进程就好了. Elixir 建立在 Erlang VM 之上, 自然也继承了这个特性 . 我不大了解其他语言在这方面, 看到 Android Studio 有支持热替换的消息 , 具体不清楚 .开发环境热替换代码对于延续C 风格的静态类型语言来说并不容易, 只是对于那些消耗性能的脚本语言来说有点意思, 比如 Lisp 系语言 (我主要接触 Scheme 和 Clojure

9、)随语言附带的 REPL 环境, 当中可以动态加载代码 , 比如 Clojure 的 REPL 可以声明 :reload 参数重新加载namespace(Scheme 方面以及 Common Lisp 方向倒是不清楚 ). 而流行脚本语言中 Node.js 可以神奇地手动清除缓存重新加载代码, Python 似乎也是类似 , 而 Ruby Pry 似乎也有不俗的效果 . Smalltalk 由于自带开发环境 , 倒是可以在 运行时中编辑替换掉方法 . 而 CommonLisp 只是大概看过OpenGL 上热替换的例子 , 而 Lua 游戏界面可能是基于Love, 也有相似热替换的方案 . 花时

10、间扒一下大概有不少 .Webpack 和 React我记得 Webpack 热替换模块出名是在2014 年下半年的样子 , 相对于以往的前端打包工具而言 , Webpack 很让人赞叹的一点是所有的模块资源被抽象成了module, 从而在Webpack 打包时所看到的是大量Module 形成的 Graph, 而不是单纯的文件 . 在这个 Graph 当中, 一个文件被修改 , 就是类似于一个更新事件, 这个事件随着Module 依赖关系一层层往上传递 , 一直到被捕获 , 或者传递到根节点引发一次页面刷新. 实际上通过 Webpack 提供的API, 很容易你就能插入捕捉事件的代码, 进行 M

11、odule 的热替换 . 在这个前端项目被越码越大且没有二进制文件不成熟的背景之下, Webpack 提供的热替换方案十分宝贵 . 我们在开发的单页面初次加载代码也许随着CPU 性能, API 网络瓶颈 , DOM 初始化因素 , 导致每一行代码修改都可能依赖数秒钟的界面重载和环境的重现, 而在热替换的情况下加上固有的文件监听延时可能几秒就好了, 成倍地压缩了时间改善着工作效率. 更可贵的是React Native 跟着把战火烧到了iOS 和 Android 两个平台 , 导致许多小公司在开发跨平台应用时机灵地盘算着省掉一半多开发者的可能性. 对于前端来说 , Webpack 的成功促使了 b

12、rowserify-hmr 的出现 , 又多了一个热替换的方案 . 给 react-hot-loader 接班的大概是Redux 方案, 也就是 Elm 给的方案 (也许很多游戏应用早就做了 , 只是我外行 ), 就是限制在全局的可变状态, 搭配尽可能不存储状态的渲染代码. 前端的代码热替换主要是替换渲染的逻辑, 打头阵的 CSS 替换甚至都不是JavaScript 运行时中间需要对付的问题 , 随后是 JavaScript 函数本身的替换 , 后面 Virtual DOM 方案将可变状态的 DOM 做了抽象的封装促成了DOM 结构能随着 JavaScript 数据做替换 . Redux 也开

13、始替换到了数据更新所使用的代码. 有点跑题 , 但是注意 , 热替换的不是数据 , 而是逻辑 , 或者说描述转换或者过程的函数. 当一段代码被完全替换时, 实际上不仅仅是代码 , 包括所有原先的代码造成的所有效果, 都需要被清理掉 , 从函数式编程的思路来说函数的效果, 一是返回结果 , 一是副作用也就是除了返回值之外的状态操作(比如往外部作用域赋值, 比如写文件 ). 其中函数返回结果 , 或者在外层函数被使用 , 或者被垃圾回收 , 不急着考虑 . 而副作用 , 两个对策 , 一个是 Elm 限制程序使用纯函数隔隔离作用, 一是 Webpack dispose 方法你自己去写回滚副作用的代

14、码. 从而在新的代码加载时就像是跟全新环境一样执行. 另一个问题是开发的代码产生的破坏性效果, 比如 Error 对整个进程的杀伤力恐怕不是 dispose 里写点代码能控制牢的 . 也有一些办法 , 主要是静态分析 , 比如 Elm 模仿Haskell 的 ADT 分析, JSX 对语法和 PropTypes 的静态检查 , ClojureScript 基于 Google Closure Compiler 实现的静态分析 , 至少思路都一致 , 就是有问题的代码尽可能早一点察觉, 根本不予执行 . 即便进程出问题了 , 重要的是核心的全局状态数据不能丢, 总是有办法把整个运行时重新生成出来的

15、 . 在这样的套路之下 , 函数式编程的纯函数和隔离状态, 就大展身手了 . 毕竟没写一段代码, 比如服务器上注册一个router handler, 当它的代码被替换需要清除时, 又需要手动调用server.removeListener 去掉 old handler 然后注册 new handler, 而且一个 server 有几十个路由 , 这种麻烦事情谁喜欢做 , 还不如一开始就采用纯函数的手段来得痛快, 最终只要把更新的代码分成几大块 , 针对性得一起处理了就好了. 而且在函数式语言的严格限制当中, 副作用也是少之又少 , 需要担惊受怕的奇怪代码也可以放心一点. 我不吐槽 JavaScr

16、ipt 转而吹捧 Clojure, 并不是后者一定更方便 , 但前者这种散漫多变实在让我不能放心托付. 今天微博上说了 , ClojureScript 和 Figwheel 环境乍一操作起来 , 坑比起 Webpack 还要多一些 , 不深入说了 , 大致上 Cirru 语法倒没什么问题 , 而是惰性计算和atom 的引用上有我这个新手不理解的地方 . ClojureScript 编译时相比 JavaScript 能检查命名空间 , 变量定义 , 参数个数 , 同时限制了可变数据使用也就避开了大部分旧代码副作用而能够直接进行替换(更像是 Amok 用 Remote Debugging Protocol 对 JavaScript 函数 body 代码进行替换那样 ), 只是更丰富的数据类型和功能确实带来了难度. 前面我用 Webpack 和 Figwheel 搭建的环境 , 一来是前端DOM 渲染采用热替换 , 避免破坏 Store 和 WebSocket 的连接状态 , 二来是服务端数据更新采取了热替换, 避免了Database( 我直接用的内存 )和 WebSocket 的状态被破

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号