小程序与普通网页开发的区别 小程序的逻辑层和渲染层是分开的,逻辑层运行在 JSCore 中。逻辑层并没有一个完整浏览器对象,因而缺少相关的DOM API和BOM API。同时 JSCore 的环境同 NodeJS 环境也是不尽相同。 小程序代码构成 JSON 配置 app.json 页面路由和页面配置 WXML 模板 MVVM 的开发模式(例如 React, Vue),提倡把渲染和逻辑分离。简单来说就是不要再让 JS 直接操控 DOM,JS 只需要管理状态即可,然后再通过一种模板语法来描述状态和界面结构的关系即可。 WXSS样式 WXSS 具有 CSS 大部分的特性,小程序在 WXSS 也做了一些扩充和修改。 新增了尺寸单位。 WXSS 在底层支持新的尺寸单位 rpx ,开发者可以免去换算的烦恼,只要交给小程序底层来换算即可,由于换算采用的浮点数运算,所以运算结果会和预期结果有一点点偏差。 提供了全局的样式和局部样式。 JS逻辑交互 WXS 提供了丰富的 API,包括系统能力。提供模块化,每个页面有独立的作用域。 小程序宿主环境 小程序的运行环境分成渲染层和逻辑层,其中 WXML 模板和 WXSS 样式工作在渲染层,JS 脚本工作在逻辑层。 逻辑层 App Service 小程序开发框架的逻辑层使用 JavaScript 引擎为小程序提供开发 JavaScript 代码的运行环境以及微信小程序的特有功能。 逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。 开发者写的所有代码最终将会打包成一份 JavaScript 文件,并在小程序启动的时候运行,直到小程序销毁。这一行为类似 ServiceWorker,所以逻辑层也称之为 App Service。 页面栈 目前,小程序的页面会被组织为一个页面栈的组合形式。 模块化 可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块只有通过 module.exports 或者 exports 才能对外暴露接口。 文件作用域 在 JavaScript 文件中声明的变量和函数只在该文件中有效;不同的文件中可以声明相同名字的变量和函数,不会互相影响。 视图层 初始渲染缓存工作原理 小程序页面的初始化分为两个部分。 逻辑层初始化:载入必需的小程序代码、初始化页面 this 对象(也包括它涉及到的所有自定义组件的 this 对象)、将相关数据发送给视图层。 视图层初始化:载入必需的小程序代码,然后等待逻辑层初始化完毕并接收逻辑层发送的数据,最后渲染页面。 启用初始渲染缓存,可以使视图层不需要等待逻辑层初始化完毕,而直接提前将页面初始 data 的渲染结果展示给用户,这可以使得页面对用户可见的时间大大提前。它的工作原理如下: 在小程序页面第一次被打开后,将页面初始数据渲染结果记录下来,写入一个持久化的缓存区域(缓存可长时间保留,但可能因为小程序更新、基础库更新、储存空间回收等原因被清除); 在这个页面被第二次打开时,检查缓存中是否还存有这个页面上一次初始数据的渲染结果,如果有,就直接将渲染结果展示出来; 如果展示了缓存中的渲染结果,这个页面暂时还不能响应用户事件,等到逻辑层初始化完毕后才能响应用户事件。 利用初始渲染缓存,可以: 快速展示出页面中永远不会变的部分,如导航栏; 预先展示一个骨架页,提升用户体验; 展示自定义的加载提示; 提前展示广告,等等。 生命周期 onLanuch 小程序启动 onRouteDone() 路由动画完成时触发。如 wx.navigateTo 页面完全推入后 或 wx.navigateBack 页面完全恢复时。 onPullDownRefresh() 监听用户下拉刷新事件。 onReachBottom() 监听用户上拉触底事件。 onPageScroll(Object object) 监听用户滑动页面事件。 onResize() 页面尺寸改变时触发。 小程序运行机制 小程序启动 从用户认知的角度看,广义的小程序启动可以分为两种情况,一种是冷启动,一种是热启动。 冷启动:如果用户首次打开,或小程序销毁后被用户再次打开,此时小程序需要重新加载启动,即冷启动。 热启动:如果用户已经打开过某小程序,然后在一定时间内再次打开该小程序,此时小程序并未被销毁,只是从后台状态进入前台状态,这个过程就是热启动。 挂起 小程序进入「后台」状态一段时间后(目前是 5 秒),微信会停止小程序 JS 线程的执行,小程序进入「挂起」状态。此时小程序的内存状态会被保留,但开发者代码执行会停止,事件和接口回调会在小程序再次进入「前台」时触发。 当开发者使用了后台音乐播放、后台地理位置等能力时,小程序可以在「后台」持续运行,不会进入到「挂起」状态 销毁 每当小程序可能被销毁之前,页面回调函数 onSaveExitState 会被调用。如果想保留页面中的状态,可以在这个回调函数中“保存”一些数据,下次启动时可以通过 exitState 获得这些已保存数据。 Skyline(替换了 webview) WXS 原先是在 渲染层 运行的,Skyline 将 wxs 挪到了 AppService(逻辑) 线程 逻辑层运行着 js 文件、以及框架逻辑 渲染引擎 Skyline,直接使用原生 GPU 渲染,其使用更精简高效的渲染管线,让 Skyline 拥有更接近原生渲染的性能体验。 当小程序基于 WebView 环境下时,WebView 的 JS 逻辑、DOM 树创建、CSS 解析、样式计算、Layout、Paint (Composite) 都发生在同一线程,在 WebView 上执行过多的 JS 逻辑可能阻塞渲染,导致界面卡顿。 在 Skyline 环境下,我们尝试改变这一情况:Skyline 创建了一条渲染线程来负责 Layout, Composite 和 Paint 等渲染任务,并在 AppService 中划出一个独立的上下文,来运行之前 WebView 承担的 JS 逻辑、DOM 树创建等逻辑。这种新的架构相比原有的 WebView 架构,有以下特点: 界面更不容易被逻辑阻塞,进一步减少卡顿 无需为每个页面新建一个 JS 引擎实例(WebView,被替换掉了),减少了内存、时间开销 框架可以在页面之间共享更多的资源,进一步减少运行时内存、时间开销 框架的代码之间无需再通过 JSBridge 进行数据交换,减少了大量通信时间开销 Skyline 特性 只保留更现代的 css 特性 组件下沉:内置组件直接在底层实现 通信时无需 bridge ,无通信开销 降低内存占用。在 WebView 渲染模式下,一个小程序页面对应一个 WebView 实例,并且每个页面会重复注入一些公共资源。而 Skyline 只有 AppService 线程,且多个 Skyline 页面会运行在同一个渲染引擎实例下,因此页面占用内存能够降低很多,还能做到更细粒度的页面间资源共享(如全局样式、公共代码、缓存资源等)。 WXSS 预编译。同 WebView 传输 WXSS 文本不同,Skyline 在后台构建小程序代码包时会将 WXSS 预编译为二进制文件,在运行时直接读取二进制文件获得样式表结构,避免了运行时解析的开销(预编译较运行时解析快 5 倍以上)。 WXS 由于被移到 AppService 中,虽然逻辑本身无需改动,但询问页面信息等接口会变为异步,效率也可能有所下降;为此,我们同时推出了新的 Worklet 机制,它比原有的 WXS 更靠近渲染流程,用以高性能地构建各种复杂的动画效果。 新的渲染流程如下图所示: worklet 函数 一种声明在开发者代码中,可运行在 JS 线程或 UI 线程的函数,函数体顶部有 'worklet' 指令声明。 共享变量:在 JS 线程创建,可在两个线程间同步的变量。
补充
补充:小程序是一套「类 Web」但「非完全 Web」的运行环境,核心差异是「逻辑层与渲染层分离 + 双线程模型 + 自定义组件机制」。
核心要点:
- 代码构成:
app.json全局配置(路由、tabBar、window 等)。WXML类似 HTML,但标签封闭集有限(view、text、image等)。WXSS类 CSS,新增rpx单位(自动按屏幕宽度换算)。JS / WXS:JS 跑在逻辑层,WXS 原本在渲染层(Skyline 后挪到逻辑层)。
- 运行环境:
- 渲染层:多个 WebView(或 Skyline 渲染引擎)。
- 逻辑层:独立 JSCore / V8 线程,运行 App Service。
- 通过 JSBridge +
setData完成数据传递。
- 生命周期:
App.onLaunch/onShow/onHide,Page.onLoad/onReady/onShow/onUnload等。 - Skyline(替代 WebView):渲染线程 + 逻辑线程独立,组件下沉原生,WXSS 预编译为二进制,内存与首屏性能更好。
补充:小程序的「双线程」主要出于安全(黑盒逻辑层)和版本独立考虑;Skyline 之后逐步把渲染层做得更接近原生,弱化 WebView 依赖。



