用现代 js 开发码良脚本

684 阅读6分钟

本文为“码良系统的使用及设计实现”系列文章的第六篇。

star history 镇楼

用ES6+写脚本

在前面的文章中,我们已经介绍过码良编辑器强大而灵活的脚本功能

不知道你有没有注意到,在编写脚本的时候,我们使用到了一些 js 的新特性(相对于 ES5),比如 rest parameters(rest 参数)、shorthand methods(对象方法简写)、shorthand properties(对象属性简写)、template string(模板字符串)、destructuring parameters(解构参数)、async(异步)等。

是的,码良脚本完全支持您使用 ES6+ 语法和新的 api。而且这并不意味着您需要使用最新的浏览器来编写脚本,也不要求终端用户必须使用最新的 webview 来浏览嵌入了 ES6+ 脚本的页面。

所以,放心大胆的用吧,用现代 js 特性加速你的脚本开发。

为什么可以用ES6+写脚本

或者说码良是如何支持 ES6+ 脚本的?我们先对这个问题进行拆解。

码良的脚本机制允许用户在页面编辑阶段编写脚本来修改/控制组件行为,在编辑器中,这些脚本编写完成立即得到执行,当页面发布以后,脚本会附加在终端页面中,在终端页面加载时得到执行。

如上所述,脚本出现的场景有编写脚本、在编辑器中执行脚本、以及在客户端执行脚本。

根据上述场景,得到如下需求:

场景 需求
编写脚本 执行前后,脚本内容(文本)不变(转码需保留源码)
编辑器中执行脚本 兼容性,需要将脚本转为ES5;脚本改变,重新转码;转码效率、频率;
客户端中执行脚本 兼容性,需要将脚本转为ES5;转一次即可;脚本执行效率;

基于如下事实,

  • 脚本不是一次性的,可以在编辑器中被修改查看,因此,必然需要保留源码。
  • 因兼容性,脚本源码在编辑器和终端页面中需要被转码为 ES5 后才能执行
  • 转码操作可以在浏览器中进行,也可以在服务端进行。
  • 浏览器中进行转码需要额外加载 babel 相关 js,会有较大的网络开销,好处是可以随时(同步)进行转码
  • 服务端转码操作占用较多服务器资源,且带来额外网络请求的开销和延迟,不适合频繁调用

我们容易得出这样一些方案:

方案一 服务端转码

场景 方案
编写脚本 从服务器获取源码;保存源码到服务器;针对源码编辑
编辑器中执行脚本 开发服务端转码接口;每次编辑完成调用转码接口对需要转码的脚本进行转码
客户端中执行脚本 请求页面结构数据时在服务端将其中的脚本进行转码,浏览器直接运行转码后的脚本

方案二 运行时转码

场景 方案
编写脚本 从服务器获取源码;保存源码到服务器;针对源码编辑
编辑器中执行脚本 添加 babel 库到编辑器,每次脚本编辑完成调用 babel 在运行时对需要转码的脚本
客户端中执行脚本 添加 babel 库到页面,获取到页面结构数据后,在浏览器中对脚本进行转码

以上两种方案都存在较大缺陷,方案一会增大服务端资源占用以及编辑器中转码网络延迟带来的不好体验;方案二在客户端中引入 babel 执行转码带来了更多的网络开销,运行时转码也会影响脚本执行效率,另外也不方便对转码结果进行缓存(如果缓存做在客户端的话,需要设计一个缓存更新机制)

为了解决上述方案的缺陷,我们给出了方案三和方案四

方案三 编辑器本地转码,存储源码+转码后代码

场景 方案
编写脚本 从服务器获取源码;保存源码到服务器;针对源码编辑
编辑器中执行脚本 添加 babel 库到编辑器,每次脚本编辑完成调用 babel 在运行时对需要转码的脚本进行转码;保存页面数据时,不仅保存脚本源码,也保存转码后的代码
客户端中执行脚本 请求页面结构数据,浏览器直接运行转码后的脚本

方案四 编辑器本地转码+终端页面服务端转码,存储源码

场景 方案
编写脚本 从服务器获取源码;保存源码到服务器;针对源码编辑
编辑器中执行脚本 添加 babel 库到编辑器,每次脚本编辑完成调用 babel在运行时对需要转码的脚本进行转码
客户端中执行脚本 请求页面结构数据时获取已在服务端进行脚本转码的数据,浏览器直接运行转码后的脚本;增加缓存机制,对转码后的页面数据在服务端进行缓存,页面更新(重新发布)后清除缓存并重新转码存入缓存

以上两个方案,编辑器部分都采用了加载 babel 进行运行时转码。在编辑器中,对网络开销不敏感,但是对转码效率和频率有较高要求,因此运行时转码比较合适。

方案三和方案四的差别主要在于终端页面中的脚本是否需要进行服务端转码,方案三直接使用编辑器转码结果,同时存储脚本源码和转码后代码供终端页面使用,方案四使用服务端转码+缓存机制。这两种方案在服务器资源占用上都得到了优化,只需要少量或不需要进行服务端转码;在终端页面加载效率上也得到了优化,无需在运行时进行转码,克服了方案一和方案二的缺陷。

当然,最终码良采用的是方案四,只存储脚本源码,在写入服务端缓存时,将脚本源码内容直接换成了转码代码,保持了页面数据结构的统一,实现了同一个详情接口在不同场景下返回包含不同格式脚本的页面数据。

最后

文章没有给出方案的具体实现,实现上也并不复杂,有兴趣的可以看看代码,这里只是记录了做这个方案时经历的一些思考和权衡,或许能给到您些许启发。

例行求体验,例行求 star