Any application that can be written in JavaScript will eventually be written in JavaScript. Likewise, any product that can be implemented using mini programs will eventually be implemented using mini programs. So how to develop a small program? The following article summarizes and shares five years of small program development experience for e-commerce front-end teams (Wanzi principle and optimization tips). I hope it will be helpful to everyone!
Questions about the underlying design of WeChat mini programs
- What exactly is the dual-thread model?
- How to separate the view and logic?
- Why use strange syntax like WXML and WXSS?
- How to block dangerous operation API?
- How to communicate and how to implement data-driven view updates?
- What are the disadvantages of the dual-threaded model?
Performance issues
The rendering thread and the JS engine thread are mutually exclusive, and there is a blocking problem. Long-term JS script execution will directly affect Rendering to the UI view causes page lag
Security issues
Dangerous HTML tags (a, script) and JS API (Function, eval, DOM API) , it is easy for attackers to tamper with page content, illegally obtain user information, etc.
Solution
The applet uses a dual-thread model to combine view display and logic The processing is executed separately in two threads. The HTML tags are encapsulated in the model. Developers cannot directly call native tags. The original dangerous logic operation API capabilities in JS are also blocked, and the communication actions involved are only Can trigger virtual DOM updates (data-driven view) through the API provided by the middle layer
2), mini program dual-thread modelThe capabilities of the view layer and the logic layer are provided through the JS file of the mini program basic library built into the WeChat client
WAWebview.jsProvides the basic API capabilities of the view layer. Including a complete set of component systems and related implementations of Virtual Dom (virtual DOM)
WAService.jsProvides API capabilities based on the logic layer and exposes APIs for various operations to developers
3), client engine underlying implementation, the view layer is rendered by WKWebView, and the environment is iOS 14 , iPad OS 14, Mac OS 11.4, etc.
, and the view layer is based on Mobile Chromium The core is rendered by the WeChat self-developed XWeb engine (from the past X5 to the self-developed XWeb engine), the view layer is rendered based on the Mobile Chrome kernel, and according to official disclosures, in the future the logic layer will also be separated from V8 and use customized Customized XWeb Worker thread, that is, customizing a Web Worker thread as the logical layer of the applet. Reference link)
is the ability to create encapsulated functions and customized elements in the browser. It consists of three main technologies Custom elementsA set of JavaScript APIs that allow defining custom elements and their behavior, which can then be used as needed in the user interface Shadow DOM A set of JavaScript APIs for attaching an encapsulated "shadow" DOM tree to an element (rendered separately from the main document DOM) and controlling its associated Function. Keeping the functionality of elements private this way allows them to be scripted and styled without fear of conflicting with other parts of the document HTML templates (HTML Template) #The template and slot elements allow you to write markup templates that are not displayed in the rendered page. They can then be reused multiple times as the basis for custom element structures Exparser is the component organization framework for WeChat mini programs, built into the mini program base library, and provides Provides basic support for various components of the program
All components in the mini program, including built-in components and custom components, are organized and managed by Exparser In the mini program, all node tree-related operations depend on Exparser, including the construction of WXML to the final node tree of the page , createSelectorQuery calls and custom component features, etc. Exparser will maintain information related to the node tree of the entire page, including node attributes, event binding, etc., which is equivalent to a simplified version of Shadow DOM implementation Based on the Shadow DOM model: The model is highly similar to the Shadow DOM of Web Component, but does not rely on the native support of the browser , and there are no other dependent libraries; during implementation, other APIs are also added to support small program component programming can run in a pure JS environment: this means that the logic layer also Have certain component tree organization capabilities (will be used in component rendering) Efficient and lightweight: good performance, especially excellent in environments with a large number of component instances. At the same time, the code size is also smaller registerBehavior Registers some basic behaviors of the component for the component to inherit registerElement Register components, the interfaces that interact with us are mainly properties and events Component creation The basic library of the mini program provides Page and There are two constructors of Component. When the applet is started, the defined fields such as properties, data, methods, etc. are written into Exparser's component registry. When initializing the page, Exparser will create an instance of the page root component, and other components used will also Create component instances accordingly (this is a recursive process) We can clearly see from the above figure It can be seen that there are differences in the communication methods between page rendering and component rendering of mini programs. Among them, the generation and diff of VDOM in Page rendering are completed in the view layer, and the logic layer is only responsible for sending data data to trigger the update logic of the rendering layer. In the rendering of Component, the logic layer and the view layer need to jointly maintain a set of VDOM. The method is to build the component's VDOM in the logic layer when the component is initialized, and then synchronize it to the view layer. Subsequent update operations will first perform a diff of the old and new VDOMs in the logic layer, and then only communicate the results after the diff, and pass them to the view layer for direct VDOM updating and rendering. The biggest advantage of doing this is to control the granularity of view update communication to the DOM level. Only the DOM that eventually changes will be updated (because sometimes changes in data do not necessarily bring about updates to the view). Compared with the previous data Level updates will be more accurate, avoiding unnecessary communication costs and providing better performance. Expand the ability of the Web . For example, input box components (input, textarea) have the ability to better control the keyboard. Better experience, while also reducing the rendering work of WebView. For example, the rendering work of more complex components such as map components does not occupy the WebView thread, but is handed over to the more efficient client for native processing. Better rendering performance, bypassing setData, data communication and re-rendering processes, for example, canvas components (canvas) can directly use a rich set of drawing interfaces To draw. After the component is created, it is inserted into the DOM tree, renders a placeholder element, and the browser kernel will Calculate the layout immediately. At this time, we can read the position (x, y coordinates), width and height of the component relative to the page The component notifies the client that the client inserts a native area at the same position according to the width and height, and then the client renders the interface in this area When the position or width and height change, the component will notify the client to make corresponding adjustments Some CSS styles cannot be applied to native components Hierarchy issues (native components are the highest level and will cover components in the WebView layer) Solution Use cover-view and cover-image components to cover the native components (limited capabilities, inflexible) Same layer Rendering (rendering native components directly to the same level of WebView through certain technical means) The same-layer rendering on the iOS side of the applet is implemented based on WKChildScrollView. After the native component is attached, it will be directly mounted to the pre-created WKChildScrollView container Principle Analysis WKWebView uses a layered approach for rendering internally. WKWebView will render the Compositing Layer (composition layer) generated by the WebKit kernel into a WKCompositingView component on iOS, but the composition layer There is no one-to-one mapping relationship with DOM nodes (the kernel generally merges multiple DOM nodes into one composition layer). WKChildScrollView: When the CSS property of a DOM node is set to overflow: scroll (lower versions need to set -webkit-overflow-scrolling: touch at the same time), WKWebView will generate a WKChildScrollView (In order to make WebView scrolling on iOS have a smoother experience, the scrolling in WebView is actually carried by a real native scrolling component, and the WebKit kernel has already processed the hierarchical relationship between it and other DOM nodes), And there is a one-to-one mapping relationship between WKChildScrollView and DOM nodes. Creation process Create a DOM node and set its CSS property to overflow: scroll and- webkit-overflow-scrolling: touch Notify the client to find the native WKChildScrollView component corresponding to the DOM node Mount the native component to The WKChildScrollView node serves as its child View Through the above process, the native component of the applet is inserted into the WKChildScrollView WebPlugin is a plug-in mechanism in the browser kernel. The same-layer rendering on the Android side of the mini program is based on the embed tag and WebPlugin. Analysis embed tag is a new tag in HTML5, which is used to define embedded content (such as plug-ins, media, etc.). The format can be PDF, Midi, Wav, MP3, etc., such as Chrome browsing The PDF preview on the browser is implemented based on the embed tag. Based on the embed tag combined with the Chromium kernel extension. Chromium supports the WebPlugin mechanism. WebPlugin is a plug-in mechanism of the browser kernel. It is mainly used to parse and describe the embed tag and render native components to the Texture texture provided by the kernel. Create an embed DOM node on the WebView side and specify the component type The Android client initializes a corresponding native component Provide the setCssToHead method to add the converted css content to the head of the html template WCC command tool execution process wcc compiles WXML to generate a JS file product The JS file contains the $gwx method, receives the WXML file path, generates the generateFunc method after execution, and triggers the generateFuncReady event generateFunc method accepts dynamic data data, similar to a render function, used to generate virtual dom Provides JS code execution environment is the window object Add module interface require define Provide Page, App, getApp and other interfaces Provide api methods under the wx global object, network, media, Files, data caches, locations, devices, interfaces, interface node information and some special open interfaces JSCore Composition (iOS, Android) 1. JSVirtualMachine It instantiates a VM environment To execute JS code, if you have multiple JS that need to be executed, you need to instantiate multiple VMs. And it should be noted that these VMs cannot interact with each other, because GC problems are prone to occur 2. JSContext JSContext is the context object for JS code execution. Equivalent to a window object in Webview. In the same VM, you can pass different Context 3, JSValue Similar to WASM, JsValue is mainly used to solve JS data types and Swift or Java data Mapping between types. That is to say, any content mounted in JSContext is of type JSValue. Swift and Java automatically implement type conversion between JS and JS internally 4, JSExport is a protocol in JSCore used to expose the Native interface. To put it simply, it will directly convert the relevant properties and methods of Native into the methods and properties on the prototype object Passed define defines a module and limits the other modules that the module can use, such as window, document, etc. The define method is implemented by storing all JS code logic in global variables in the form of "path-module" key-value pairs. The 1. iOS side 2. Android side 3. WeChat developer tools invoke:JS calls Native API on:JS listens to Native messages publish:View layer publishes messages subscribe: Subscribe to messages from the logic layer web front-end] Download the mini program code package, load the mini program code package, and initialize the mini program homepage From a developer's perspective, controlling the size of the code package helps reduce the startup time of the mini program. For code packages less than 1MB, the download time can be controlled within 929ms (iOS) , 1500ms (Android) Optimization plan Reduce the size of main package and sub-package Reasonable allocation, sub-package preloading rules Fine splitting, asynchronous subcontracting Before starting the mini program , WeChat will prepare a page level in advance to display the homepage of the mini program. Whenever a page level is used to render a page, WeChat will start preparing a new page level in advance, so that each time wx.navigateTo is called, a new page can be displayed as soon as possible. The content of the view layer page is generated through the pageframe.html template Preparation steps for the page level The first stage is to start a WebView. On iOS and Android systems, it takes a short time for the operating system to start the WebView. The second stage is Initialize the basic library in WebView. At this time, some internal optimizations of the basic library will be performed to improve page rendering performance The third stage is to inject the WXML structure and WXSS style of the mini program to make the mini program The program can start rendering the page immediately after receiving the initial data of the page (this stage cannot be executed before the mini program is started) View layer global variables Logical layer global variables View layer code injection Logic layer code injection On-demand injection and time-consuming injection Normally, when the mini program is started, all JS codes in the sub-package and main package (except independent sub-packages) where the startup page is located will be Merge injection. Since the basic library version 2.11.1, on-demand injection and time-based injection are configured. The applet only injects custom components and page codes required by the current page, and customizations that will not be used in the page. Components will not be loaded and initialized Data communication When the applet is started or a new When the page is opened, the page's initial data (data) and path and other related information will be sent from the logic layer to the view layer for the initial rendering of the view layer. The Native layer will pass these data directly to the view layer, and at the same time present a new page level to the user, and the view layer will draw the interface on this page level. After the view layer receives the relevant data, it selects the appropriate WXML structure according to the page path. The WXML structure is combined with the initial data to obtain the first rendering result of the page After completing the view layer code injection and receiving the initial data sent by the logic layer, combined with the page structure and style information obtained from the initial data and the view layer, the mini program framework will render and display the mini program homepage. The first screen of the mini program and triggers the onReady event on the home page. If Initial rendering cache is turned on, the first rendering can be completed directly using the cached data of the rendering layer, without relying on the initial data of the logic layer, reducing startup time (onReady event is executed in advance). #The page initialization time is roughly composed of two parts: the page's initial data communication time and the initial rendering time.
Among them, the data communication time refers to the time from the beginning of data organization at the logical layer to the completion of complete reception by the view layer. When the data volume is less than 64KB, the total time can be controlled within 30ms. The transmission time is generally positively correlated with the amount of data. Transmitting excessively large data will significantly increase this time.
Therefore Reducing the amount of transmitted data is an effective way to reduce data transmission time. Initial Rendering Initial rendering occurs when the page is just created. During initial rendering, the initial data is applied to the corresponding WXML fragment to generate a node tree. The node tree is the page tree structure seen in the WXML panel of the developer tools. It contains information such as the names, attribute values, event callback functions and other information of all component nodes in the page. Finally, according to each node contained in the node tree, each component is created sequentially on the interface. The data and current node tree obtained in the initial rendering will be retained for re-rendering. In this entire process, the time overhead is generally proportional to the total number of nodes in the node tree. Therefore Reducing the number of nodes in WXML can effectively reduce the time overhead of initial rendering and re-rendering and improve rendering performance. After the initial rendering is completed, the view layer can perform interface updates after the developer calls setData. setData Principle 1. Change the value of the corresponding this.data (synchronous operation) Parse the attribute name (including . and [], etc. Data path symbol), return the corresponding hierarchical structure, modify the value of the corresponding local data 2. Send data from the logic layer to the view layer (asynchronous operation) evaluateJavascript : The data transmitted by the user needs to be converted into a string for transmission. At the same time, the converted data content is spliced into a JS script, and then passed to the independent environments on both sides by executing the JS script. When re-rendering, the logic layer merges the setData data into data, and the rendering layer applies the data and setData data to the WXML fragment to obtain a new node tree. Then compare the new node tree with the current node tree, so you can get which nodes need to be updated and which nodes need to be added or removed. Finally, the old node tree is replaced with the new node tree for the next re-rendering. When comparing the current node tree and the new node tree, the node attributes affected by the setData data will be compared. Therefore, removing unnecessary set data and reducing the amount of data in setData will also help improve the performance of this step. The view layer will accept user events, such as click events, touch events, etc. The communication of user events is relatively simple. When a user event is triggered and a related event listener needs to be triggered, the view layer will feed the information back to the logic layer. Because this communication process is asynchronous, a certain delay will occur. The delay time is also positively related to the amount of data transmitted. When the data amount is less than 64KB, it will be within 30ms. There are two main ways to reduce the delay time Remove unnecessary event binding (bind and catch in WXML ), thereby reducing the amount and frequency of communication data When binding events, you need to transmit the dataset of target and currentTarget, so do not place too large data in the data prefix attribute of the node 主包内容 Tab页(系统要求)、业务必要页面(错误兜底页、登陆授权页等),其余文件都以业务模块或者页面的维度,拆分成各自的分包 分包预加载 据用户的实际使用场景,预测下一跳的页面,将可能性最高的场景设置为预加载分包(可以参照业务埋点数据),例如:进入电商首页后,需要对会场和商详页的分包进行预加载 实现思路 小程序不支持主包引用分包代码,只能在分包中引用主包代码,所以把公共使用的组件代码放在主包目录中,但这些公共组件未必在主包所属的页面中会被引用,可能只是在分包页面中被多次引用,这样使得主包中代码体积越来越大,用户首次加载速度变慢。 将主包页面不依赖的公共组件分别分发到依赖它们的分包目录中,虽然分包各自的体积会有所增大,但主包体积会有显著下降 实现原理 将所有需要分发的组件放置主包指定目录中,并添加配置文件,说明组建文件分发信息。在开发时用 gulp 任务监听单个文件变化、在构建时递归遍历所有组件,将其复制到配置文件中指定的子包路径目录中。 目标文件在复制之前,都先要将文件内的依赖路径进行更新,使其在子包中运行时也能引用成功。针对不同类型的文件,采取不同的依赖分析手段。 JS 文件:使用 babel.transformFile 修改依赖引用地址 WXSS 文件:使用 postcss.plugin('transform-wxss') 处理依赖的 @import 导入样式文件地址 WXML 文件:使用 require('htmlparser2').Parser 来转换内部 wxs、template(import 和 include 导入)依赖的引用地址 异步分包 小程序基础库版本 2.17.3 及以上开始支持分包异步化,即可以在分包之间互相引用,这个能力可以快速取代我们自己的组件分发方案,而且优化效果更佳,可以将分包中公共依赖的代码部分打成新的分包,在使用时异步按需引入,能力与 Web 端的异步组件类似,但这个方案在生产环境的稳定性有待验证。 实现思路 合并 setData 调用,将其放在下个时间片(事件循环)统一传输,降低通信频率 实现原理 需要先将逻辑层 this.data 进行更新,避免前后数据不一致造成逻辑出错。将需要传送至视图层的 data 进行整合,在 nextTick 中调用原生的 setData 统一进行传送,可以有效降低通信频率,并且在传送前手动做一次与 this.data 的 diff 操作,降低通信体积 1. 降低频率 2. 减少体积 参考京东 Taro 中 diff 的实现,对基本、数组、对象等不同类型进行处理,最终转换为 arr[1]、x.y 这样的属性路径语法,减少传输信息量 实现思路 onLaunch、onLoad 等生命周期函数中存在大量对微信 Storage 的同步调用(使用 Sync 结尾的API),这些操作涉及JS与原生通信,同步等待耗时过久,推迟页面 onReady 触发即用户可交互时间,影响用户体验。直接改为异步操作又存在业务代码改动量较大的问题,存在一定风险,大量的异步回调代码语义不优雅、可读性较差。因此需要对原生 Storage 操作进行重封装,改为对内存中对象的实时存取,提高响应速度,并定期调用原生 API 向真实 Storage 中同步。 实现原理 Encapsulate APIs with consistent calling methods, with getStorage and getStorageSync as the basic APIs. When called for the first time, the native API is triggered to obtain the original data. After obtaining it, it is stored in a memory object. All subsequent operations (deletion, modification, and query) are based on this object. Do the operation. The set and remove operations need to mark the corresponding data as dirty and store it in a dirty table so that the changes can be synchronized to the native end later. The caller needs to call the change synchronization method regularly to persist the data (traverse the data in the synchronized dirty table) to prevent accidental data loss when the memory is running. Generally, it needs to be executed regularly (the app's onShow executes setInterval) and executed in the app's onHide life cycle. . We have not only re-encapsulated the Storage API, but also used other synchronization APIs that take a long time (such as the getSystemInfo/getSystemInfoSync API used to obtain device and system information, the underlying implementation is synchronous). In a similar way, the system API is called only during the first acquisition and the result is cached in memory, and subsequent calls directly return the cached information. Implementation ideas From A Before the page jumps to page B, the emit message of page A triggers the data interface request of page B and caches the result data. When page B is opened, the cache is first fetched. If it cannot be fetched, the interface is called again Implementation Principle Although page B has not been instantiated, the page has been registered and the outer code of Page has been executed, so the message can be completed with page A in advance Publish and subscribe Implementation ideas When the page that needs to be preloaded is not registered in the main package or asynchronously , it is impossible to perform pre-requests through the publish and subscribe mode. We can achieve this by globally registering the preloading method. Implementation principle Route jump on the previous page Initiate a pre-request, save this request to a global Promise variable, and when the page that needs to be pre-loaded is rendered for the first time, the data result in the global Promise variable then callback will be taken first Optimize the overall image resources (Alibaba Cloud function) Implementation ideas According to the user model hardware performance level, the front-end display sets different presentation strategies Implementation principle Downgrade the following functions in low-end machine scenarios Framework tools BeautyWe is a three-party small program business development framework that encapsulates the underlying public business logic of life Application scenarios Public business logic, such as verification of user login status on each page, obtaining and processing url parameters, automatic PV burying, performance monitoring, etc. Implementation Principle The life cycle function is plug-in, and the native onLoad, onShow, onReady and other functions are rewritten using Object.defineProperty to form a Promise task chain internally. By introducing plug-ins, methods can be freely inserted into the front and back positions of the task chain. The system life cycle functions are triggered when they are executed and called in sequence. After implementing the plug-in of the life cycle hook, we can encapsulate all types of underlying public logic that need to be processed and insert it into the host (native life cycle) Promise task chain Based on the mini program CI Gitlab CI Puppeteer, a set of semi-automatic mini program construction and deployment tools is implemented. For details, see my other article "WeChat Mini Program Automated Deployment Solution" , the WeChat Mini Program later provides miniprogram-ci that can be run independently in the Linux environment, making it simpler and easier to use. Monitoring capability Business hidden point (Business focus such as page PV, module exposure, etc.) Performance reporting (mini program startup, page rendering, FMP, memory alarm) Exception monitoring (JS error, interface error, business error) Performance monitoring reporting type memory_warning: Memory alarm data reporting. Collection method: Collect alarm levels in wx.onMemoryWarning callback app_launch: App runtime data reporting. Collection method: Record the app life cycle execution time (onLaunch, onShow), and report it when the page is onLoad page_render: Page runtime data reporting. Collection method: Record the page life cycle execution time (onLoad, onShow, onReady), FMP, etc., and report it when the page is onHide or onUnload Implementation principle Based on the plug-in framework, rewrite the life cycle hook function to automatically record and report performance data during the execution of the page program We use FMP as a key indicator to measure the second opening rate. For details, please refer to my other articleUser experience-centered front-end performance optimization. In addition, in daily development, we have also precipitated some specifications that can improve the basic guarantee of performance and stability in daily business iterations. For details, see WeChat Mini Program Development Military Regulations. The official documents have continued to improve the underlying technology of the framework The disclosure shows that the technology construction of mini programs is becoming increasingly mature and perfect. With the continuous enrichment of the infrastructure ecosystem, officials have successively provided support for these capabilities, including same-layer rendering, network environment monitoring, initial rendering caching, and startup performance optimization, gradually bringing mini programs closer to the Web ecosystem. In our own business iteration, in order to solve various problems, we have created many wheels ourselves, such as: subcontracting and asynchronousization, CI packaging, and performance API. WeChat will later implement these capabilities natively. It may seem like a useless effort, but in fact it just shows that what we have done in the past is correct, and the direction is consistent with the development of the entire ecosystem. In addition to the improvement of technical capabilities, the WeChat mini program ecosystem is also constantly enriching capability support in more business scenarios, such as Support mini programs for sharing Moments, generating short links, and WeChat chat materials to open mini programs, providing more possibilities and imagination for our business. WeChat has also launched a mini program hardware framework, which allows hardware devices (non-general computing devices) to run WeChat mini programs even if they lack the conditions to run the WeChat client. It can be used on Android tablets, tablets, etc. in all walks of life. Hardware such as large-screen devices provides low-cost screen interaction solutions and provides IoT device users with a more standardized and feature-rich experience. This reminds me of the saying Atwood's Law that has been circulating in the field of computer technology for decades. Any application that can be written in JavaScript will eventually be written in JavaScript. Likewise, any product that can be implemented using mini programs will eventually be implemented using mini programs. Since the birth of WeChat mini programs in 2017, the super App mini program/light application model has been tried and tested in various businesses, such as WeChat and WeChat mini programs, Alipay and Alipay mini programs, Douyin and Douyin mini programs, etc. Mini programs, a product model with low cost, fast iteration and easy promotion, have been used in various fields with the support of huge traffic brought by super apps. All have achieved great success and have gradually become a trend, with more and more companies adding this model to their products. The mini program itself has been unknowingly integrated into every aspect of life. During the epidemic, health code applications in various regions, mini program codes for e-commerce group purchases in the community, and restaurant ordering, if you want to drink milk tea and coffee, you can download them in advance on the mini program. In fact, people's lives are inseparable from small programs. The product technology solution of small programs has indeed created great social value. When I was chatting with a friend, I jokingly said that mini programs are PWA applications with Chinese characteristics. Facing the future, mini programs still have great potential. In addition to the existing online shopping and life service applications that account for a relatively high proportion, they are also used in more The usefulness of mini program technology can also be seen in various scenarios. For example, in the fields of health care, offline retail, entertainment games, AI intelligence and other industries, it is far from reaching saturation. The market gap has made the development potential of mini program become more and more important. To get bigger, Mini Programs are moving towards the original goal of making Mini Programs within reach and everywhere. Original address: https://juejin.cn/post/7100752247381819399 (Learning video sharing: Getting started with web front-end)
2. Exparser framework
3. Exparser features
4. Exparser core method
5. The creation process of Page and Component
3), Mini Program native components
1. Advantages of native components
2. Native component creation process
3. Native component rendering restrictions
4), rendering native components on the same layer
1. iOS system implementation principle
2. Android System implementation principle
wcsc Compile WXSS to generate a JS file Product
The JS file contains a conversion method to add size unit rpx, which can be used according to the device screen The width is adaptively calculated into px units
2. WXML code file
3. Logical layer
1), the logical layer contains content
2), JS code execution environment
3. Implementation of module specifications
This is actually a typical module loading idea, which is very similar to the way Webpack packages modules. 4. Communication principle In WAWebview.js and WAService.js files In addition to providing the basic API capabilities of the view layer and logic layer, it also provides the ability to communicate between the two threadsThe communication between the applet logic layer and the rendering layer will be done by Native (WeChat client) For transfer, the logical layer sends network requests and also forwards them through Native1), and the underlying implementationThe different implementations of several ends will eventually be encapsulated into a compatibility layer like WeiXinJSBridge for developers to call
##5. Defects and optimizations of dual-thread architecture
1) Defects of dual-threaded architecture
2), optimization of dual-thread architectureThe performance bottleneck caused by dual-threads, This is also a key issue that WeChat itself has been committed to solving. As mentioned earlier, the applet will replace the implementation of the logic layer with a custom XWeb Worker thread by modifying the Chromium kernel in the new XWeb kernel. This will eliminate the need for additional V8 and significantly increase memory usage. reduce. In addition, since it is based on the Worker thread of the Chromium kernel, regarding data communication, it is natural to have the ability of PostMessage to replace the original setData underlying communication method to obtain higher performance communication capabilities
3), the dual-thread architecture of the Alipay appletIn addition, I also learned about and studied the underlying implementation of the Alipay applet. The Alipay applet also uses a similar dual-thread architecture model. By using the browser kernel provided by UC, the rendering layer runs in the Webview thread, and the logic layer starts a separate thread to run the Service Worker. However, the Service Worker needs to communicate with the rendering thread through the MessageChannel API. When the amount of data is large and the objects are complex, there are also performance bottlenecks. Therefore, the Alipay applet redesigned the existing JS virtual machine V8 and proposed an optimized isolation model (Optimized isolation model, OIM). The main idea of OIM is to share data and infrastructure in JS virtual machine instances that have nothing to do with the thread execution environment, as well as immutable or immutable JS objects, so that while maintaining the logical isolation of the JS layer, memory can be saved in multi-instance scenarios. and power consumption overhead. Although some data shared between instances will bring synchronization overhead, under the isolation model, the data, objects, code and virtual machine infrastructure shared by this solution are immutable or non-volatile, so competition rarely occurs. Under the new isolation model, the V8 instance in the Webview is a Local Runtime, and the V8 instance in the Worker thread is also a Local Runtime. When the logic layer and the rendering layer interact, the setData object will be created directly in In the Shared Heap, the Local Runtime of the rendering layer can directly read the object and use it for rendering of the rendering layer, which reduces the serialization and network transmission of the object and greatly improves startup performance and rendering performance. In addition, the Alipay applet implements homepage offline caching optimization. It first renders the homepage UI page saved last time, displays the homepage to the user, and then continues to load the front-end framework and business code in the background. After the loading is completed, it is merged with the offline cached homepage UI to display a dynamic homepage to the user. This is very similar to the initial rendering caching scheme of the WeChat applet and is more radical. WebAssembly technology was also used to reimplement the core code of the virtual DOM and improve the page rendering of the mini program. [Recommended related video tutorials: 6. Thoughts on the design of dual-thread model architecture
Technical architecture is born to solve problems , a good technical solution not only requires designers to make balance and trade-offs between development efficiency, technical cost, performance experience, and system security, but also needs to be closely integrated with business trends, product forms, and user demands
2. A closer look at the runtime mechanism
1. Code package download
When the mini program starts (cold start), WeChat will The program displays a fixed startup interface, which contains the icon, name and loading prompt icon of the mini program
At this time, WeChat will complete several tasks behind the scenes:
2. Page level preparation
3. Page code injection and execution
1), initialize global variables
2), basic library and business code JS file injection
3), logic layer business code execution
4, data communication and View rendering
1), page initial rendering
2) Update data rendering
{abc: 1} 中 abc 属性名 => [abc]
{a.b.c: 1} 中 'a.b.c' 属性 => [a,b,c]
{"array[0].text": 1} => [array, 0, text]
3), user event communication
三、小程序基建和优化方案实践
1、小程序性能优化
1)、代码分包
1、合理的分包和分包预加载策略
2、组件分包分发
2)、setData 优化
const nextTick = wx.nextTick ? wx.nextTick : setTimeout; // 小程序里的时间片 API
3)、Storage API 重封装
4), Data Prefetch
1, Publish and subscribe method
2. Global registration variable method
5) , Memory optimization
1. Image optimization
2. Low-end machine downgrade
3. Long list optimization
2. Mini program engineering
1) Plug-in framework
2), automated deployment
3), hidden point monitoring
3. Performance optimization implementation and daily Iteration specification
4. Summary thinking and development prospects
Continuous improvement of infrastructure capabilities
More scenarios to empower business
Prospects for the development of mini programs