如果Web一开始不支持动态化本文转载请联系前端公众号向后。WedgeWeb天生具有极其灵活和动态的基础能力,例如:动态插入脚本标签执行任意脚本逻辑动态插入样式标签引入任意CSS样式规则通过iframe标签嵌入整个站点以上标签可以直接加载网络资源来承载这些内容网页部署在远程服务器上,可随时动态更新,并可立即生效。长期的探索和实践,似乎是在不断探索动态能力的工程价值,寻找更适合它的应用场景,比如早期的frameset,以及现在移动端的微前端/微app。恰恰相反,并且有很多灵活性限制:原生不支持逻辑代码的动态执行。在用户设备上,安装包更新需要应用商店审核,用户只能重新安装才能生效。移动业务的发展对动态能力不断提出更高的要求。但由于缺乏动态的基础能力,探索了更灵活的解决方案。技术方案,比如早期的热修复/热更新,到今天的小程序,其实在动态技术能力上,比如动态加载依赖库,视图组件,甚至整个应用,都有同样的工程问题需要解决。所以不惜开个脑洞,假定Web不支持动态化,以Native的业务诉求来推演Web动态化技术的发展轨迹伊始:原生WebAssembly0061736d010000000187808080000160027f7f017f0382808080000100048480808000017000000583808080000100010681808080000007908080800002066d656d6f727902000367636400000aab8080800001a58080800001017f02402000450d0003402001200022026f21002002210120000d000b20020f0b20010b从前,Web应用程序只能被打包成这种wasm的二进制格式,发布Goto主要的浏览器应用程序商店。这期间不仅要等几天审核,还要等用户通过后主动安装更新,等到新版本真正“生效”(覆盖大部分用户),这可能是几个月后。版本变更缓慢,无论是战略重要功能还是紧急问题修复都无法及时到达用户手中。即使网上发生火灾,最快的灭火方案也需要数天甚至数周才能生效。为了更快的修复问题,降低风险,热修复方案的探索从这里开始:介绍热修复的脚本语言JavaScript热修复是指加载运行逻辑代码(安装包外),所以一些人们直接从WebAssembly模块加载机制入手,开发一些Hook方案,可以动态替换一些模块/文件,也有人沿着这个方向更进一步,权衡时效性、性能、兼容性和稳定性,解决诸如通过编译存根、工程配套设施、运行时框架等方式实现模块依赖、版本管理、差异更新。有人另辟蹊径,将各种功能模块进行插件化,引入轻量级的脚本语言运行时(如JavaScript引擎),并在浏览器原生的WebAssembly和JavaScript世界之间架起一座桥梁,让原生系统平台能力通过JavaScript调用关系,从而扩展了动态化的基本能力。动态化掀起涟漪,随之而来的是动态更新海啸:基于JavaScript的动态更新在动态化方向迈出第一步后,距离完全动态化还很远。前景仅一步之遥:任何可以用JavaScript编写的应用程序,最终都将用JavaScript编写。-JeffAtwood(来自最小功耗原则)完全动态意味着:任何可以动态编写的应用程序所有现代化的部分都由JavaScript实现。将庞大的JavaScript代码组织成功能模块,很好地管理功能模块之间的依赖关系,实现以功能模块为单位的快速迭代,相当于应用hotfix技术进行问题修复。除了需求迭代,无需发布版本,无需审核周期,无需等待用户主动安装。新功能可以动态发布,快速被活跃用户覆盖,JavaScript在应用程序中的比例越来越高,最后只有不能动态化(或不需要)的部分仍然由WebAssembly实现,包括:桥接基本UI控件的系统平台能力,交互能力视图层框架(历史堆栈管理、生命周期支持等)特定业务领域能力(例如如多媒体内容制作、IMSDK等)通信机制(广播、状态共享等)这些部分组成了一个容器(nativeshell),相当于一个运行在浏览器中的动态运行时。在容器圈定的能力范围内,业务可以充分利用动态优势,实现快修复、快发布、快访问、快迭代。但是随着容器概念的出现,除了可以让业务跑得更快之外,还有动态业务与容器之间的依赖问题。:如何去掉两者之间的强耦合,比如路由、混合视图容器等场景?如何识别两者之间的依赖关系?如何保证依赖可控,比如禁止在旧容器中发布依赖新能力的动态服务?在工程支撑控制好依赖关系之后,接下来的首要问题是如何保证动态业务所依赖的底层容器的可靠性边界:HTML、JavaScript、CSS构成容器标准。通常隔离变更的手段是增加一个抽象层,将变更的部分放在抽象层下:BOMAPI:系统平台、视图层框架能力、通信机制的抽象NativeModuleAPI:具体业务领域能力的抽象DOMAPI:基本视图的渲染能力的抽象JSAPI:JavaScript运行时的抽象CSS:样式和布局能力的抽象HTML:基本UI控件和交互能力的抽象这些抽象的标准建立了坚实的容器边界,在边界之内,动态业务可以发挥自由,在边界之下,容器也可以不断完善,丰富容器能力,拓宽边界。同时,可以将定义标准的API以结构化的形式进行维护,对开发体验大有裨益。云海:浏览器支持加载网络资源另一方面,在标准化的过程中,一些动态的业务实践也被沉淀到容器中,例如:动态脚本:脚本支持加载网络资源动态样式:样式支持加载网络资源Dynamic路由:浏览器支持直接通过URL加载或通过iframe嵌入Web应用,虽然自热修后可以从CDN拉取JS文件,并在运行时动态解释执行,但容器标准不仅提供了对这种方式的便捷支持,还提供了动态基础能力从逻辑扩展到视图、样式、静态资源等,至此,最关键的动态化基础能力已经完成。迁移到JavaScript的功能模块甚至可以进一步部署到云端,实现离线集成和在线托管模式的灵活切换:同步和异步模式自由切换。完备的动态基础能力解锁多种新玩法,如:模块化(Loader)代码拆分SSRHydrationlazycomponentSuspense将业务模块(bundle)进一步拆分为功能模块(chunk),将非核心模块异步发送出去实现动态按需加载,如第三方JSSDK、jQuery插件,以及分享/评论/城市选择等重组件,对于静态内容渲染场景,(大部分)页面渲染工作也可以通过SSR在服务端完成,加速首屏内容的显示;另一方面,Hydration、lazycomponents、Suspense等运行时特性使得在线动态部分与离线非动态部分充分融合,实现更精细-精细的业务活力,使在线托管成为真正的部署选项。同时,动态业务本身的组件化也在不断增加。随着不断深入,前端开发的核心工作已经从页面、模块开发转向组件、编排逻辑开发。流云:在数据驱动的前端应用组件体系趋于成熟之后,一个由来已久的概念终于浮出水面——数据驱动,从前后端分层的数据协议,逐渐演变为数据驱动.这里的数据包括3部分:后端业务域数据前端状态数据(基于后端业务域数据)前端派生数据将这些数据填充到业务组件中,就可以渲染出一个完整的功能模块(无论是在客户端或服务端),然后将其放置在视图容器中合适的坑中,完成一个组件级的“发布”过程。该模式涉及5个重要环节:业务数据的生产(包括后端业务域数据和前端派生数据)业务组件(包括前端状态数据)和维护组件(业务数据+业务组件=功能模块)坑生产功能模块其中,业务组件和坑是进一步动态化的关键,分为4个阶段:一个萝卜一个坑:静态业务组件+静态坑,一个萝卜到处扔:静态业务组件+动态坑,多个萝卜轮流扔:动态业务组件+静态坑到处扔多个萝卜:动态业务组件+动态坑要达到组件级动态到处扔多个萝卜的最终目标,需要能够动态发布业务组件,动态发布坑Blending:DynamicBusines组件+动态的坑从设备和云端的角度来看,业务组件也可以看作是数据(云端)的一部分。相比之下,坑与事物上云的关系更为密切,因此要解决的关键问题是如何实现坑的动态化。思路有两种:去掉坑的概念:将坑的概念从组件级扩展到页面级,一个页面容器(一个URL)即坑组件化坑:提供标准的坑组件,就像iframe一样页面是一个天然的动态坑,可以打开一个新的页面容器,加载除页面以外的其他布局容器的任意URL,例如对话框、消息条、横幅位、腰带等,坑可以标准化为容器组件,即可以和业务组件一起动态发布,作为数据驱动数据在服务端维护坑的租用关系。至此,前后端层的界限被重新定义了数次,终于迎来了JSP/PHP融合数据和模板的黄金时代……原文链接:https://mp.weixin.qq.com/s/MssledyYt_2gqZ5Q7xgjFg
