# The logic layer and the view layer are separated, and there will be communication loss on non-H5 sides
When uni-app runs on the non-H5 side, it is divided into two parts: logic layer and view layer. The logic layer executes business logic, i.e., running js code, while the view layer executes page rendering.
Although developers write js and css in a vue page, they actually have been split while being compiled.
The logic layer runs in an independent jscore instead of depending on the webview of the native computer. On the one hand, it does not have the problem of browser compatibility, and can run es6 code on Android4.4; on the other hand, it can't run browser-specific js API in browsers such as window, document, navigator and localstorage.
jscore is a standard js engine, standard js can run normally, such as if, for, various strings, date processing, etc. The difference between js and browser should be distinguished.
The so-called js engine of browser means to add a number of browser-specific API, such as dom, on the basis of jscore or v8.
node.js engine means to supplement some computer-specific API on the basis of v8, such as local io;
Then, the js engine on the App side of uni-app actually supplements a number of commonly used mobile phone side JS API on jscore, such as scanning.
On the H5 platform and app-vue, the view layer is webview. The view layer of app-nvue is a native rendering view based on weex transformation.
With regard to webview, you can only use webview provided by iOS on iOS (the default value is WKWebview). It has some browser compatibility problems, and its performance is slightly different (generally negligible) due to different iOS versions.
There is no way to run such a large third-party package on the App side on Android, so the App side uses the Android system webview by default, which varies according to different mobile phones. Of course, the App side also supports Tencent X5 engine, and the view layer can be unified on the Android side at this time.
Therefore, js of uni-app basically has no compatibility problem with different mobile phones (because the js engine comes with it), while the css in the view layer will have compatibility problems with the css of mobile browsers when using system webview on app-vue. At this time, either don not use too new css syntax or integrate Tencent x5 engine.
# Pros and cons of separation of logic layer and view layer
The advantage of separating the logic layer from the view layer is that js operation does not stagnate rendering. The simplest and most direct feeling is that the window animation is stable.
If developers have used App, they should have the idea that if making the entry animation and rendering itself at the same time, the new webview window is very likely to stagnate animation. uni-app, on the other hand, does not need to write preload code, and the new window is rendered quickly and the animation is stable.
However, the separation of the two layers also brings a disadvantage, that is, it will cause loss while the two layers communicate with each other.
It is not so bad for iOS, but for Android low-end phones, every communication takes tens of milliseconds. The effect is usually not visible, but it is very obvious in some scenarios.
If you draw canvas animation at high frame rate continuously, you will find that it is not as smooth as drawing inside webview
The view layer scrolls, operates with hands, and feeds back to the logic layer continuously, then js processes the logic and informs the view layer to make corresponding updates. At this time, you may find that the interaction does not follow the hands or gets stuck
Both app-vue and app-nvue have this two-layer communication loss problem.
To solve this kind of problem, different methods are referenced in webview rendering and native rendering:
In app-nvue, loss exists in both logic layer and view layer. react native has this problem too. It can be seen that native rendering is not that advanced.
weex provides a set of bindingx(opens new window) mechanism, through which an expression is passed to the native layer at a time in js, and the native view layer is parsed by the native layer according to instructions to avoid repeated cross-layer communication. This technology can also be used in uni-app.
Bindingx, as a kind of expression, is not as powerful as js, but it can still implement gesture listening to and animation. For example, uni ui's swiperAction component will automatically enable bindingx when running under app-nvue to achieve smooth follow-hand experience.
If a large number of large image resources are used in the page, the switching of pages will be stagnated, and the system memory will increase, even crash with a white screen.
In particular, do not display multiple large images on one screen after being reduced. For example, if you select a few megabytes of photos before uploading the images, and then zoom them out to display on one screen, it is very easy to crash the white screen.
Converting large-volume binary files to base64 is of extremely resource-consuming.
In uni-app, every time the data defined in data changes, the view layer will be notified to re-render the page. Therefore, if it is not a variable needed by the view, it doesn’t have to be defined in data, it can be defined externally or mounted directly on the vue example to avoid wasting resources.
If there is a like button for each item in the long list, click it and the number of like +1, at this time, the like component must be a single referenced component to update the variance data. Otherwise, it will result in the overload of the whole list data.
Each item in the long list does not necessarily need to be made into a component, depending on whether you need to update the data of a row of items by variance in your business. If there is no such requirement, it is not recommended to introduce a large number of components. (After clicking item, the background changes color, which belongs to css adjustment. If data and rendering are not updated, this problem will not exist)
When there is a large amount of data in a single component (such as a long list), it will take a lot of time to update the data on the App side. It is recommended to use components to paginate the data and limit the changes to a smaller scope. You can refer to: Example of long list optimization(opens new window)
The long list of nvue on the app side should use the list component, and there is an automatic rendering resource recycling mechanism. For vue pages, page scrolling provides better performance than area scrolling using scroll-view. uni ui encapsulates uList component, uses list component under app-nvue, and uses page scrolling and automatic adaptation in other environments. It is highly recommended for developers to use it to avoid performance problems caused by poor writing.
If you need a long list that slides left and right, please create a new uni-app project selecting news template in HBuilderX, which is a benchmark implementation. If it is built with swiper and scroll-view, performance problems are easy to cause.
# Reduce the number of nodes for one-time rendering
When the page is initialized, if the logic layer transmits a large amount of data to the view layer at one time, and the view layer renders a large number of nodes at one time, it may cause slow communication and page switching stagnation, so it is recommended to render the page by partially updating the page. For example, if the server returns 100 pieces of data, it can be loaded in batches, loading 50 pieces at a time, and loading the next batch after 500ms.
#Reduce the number of components and the nesting level of nodes
Deep nested nodes often need to occupy more memory when the page is initialized and built, and they will be slower when traversing nodes, so it is recommended to reduce deep nested nodes.
When some nvue pages are first rendered on Android low-end phones, they will see the rendering process from top to bottom, which is often caused by too many components. Communication will be triggered once when each component is rendered, and too many components will block communication.
# Avoid frequent communication between view layer and logic layer
Reduce the listening to of the scroll events of the scroll-view component, when listening to the scroll events of the scroll-view, the view layer will frequently send data to the logic layer;
Don't change scroll-top/scroll-left attribute in real time when listening to scroll-view component, because when listening to the scroll, the view layer communicates with the logic layer, and when changing scroll-top/scroll-left, the logic layer communicates with the view layer, which may cause communication stagnation.
Pay attention to the use of onPageScroll, when onPageScroll is listening to, the view layer will frequently send data to the logic layer;
It is recommended to use css animation instead of animation through the js timer interface
If you need the follow-hand operation in canvas, it is recommended to use renderjs at the app side.
During the initialization of the page, if there are a lot of images or native component rendering and a lot of data communication, new page rendering and window entry animation will happen to grab resources, resulting in page switching stagnation and frame dropping. It is suggested to delay rendering images or complex native components for 100ms-300ms, and communicate data in batches to reduce the number of nodes rendered at one time.
The animation effect on the App side can be customized. Double-window linkage extrusion animation effect of popin/popout consumes more resources. If js is executed in the page during animation, it may cause the animation to drop frames. At this time, you can use animation effects that consume less resources, such as slide-in-right/slide-out-right.
If the page background is dark in color, the new window might be grayish-white background at the beginning of animation in vue page, and then it becomes dark background at the end of animation, causing flicker. This is because the background of webview takes too long to become valid. At this time, you need to write the style in App.vue to speed up the page style rendering speed. App.vue The style inside is a global style. Every time a new page is opened, the style in App.vue will be loaded first, and then the style of the normal vue page will be loaded.
app side can also configure the page native background color separately in the style of pages.json page, for example, configure the global background color under globalStyle->style->app-plus->background
"style":{"app-plus":{"background":"#000000"}}
In addition, nvue page does not have this problem, and it can also be changed to nvue page.
Note: The above optimization scheme runs on HBuilderX 2.7.7 and is not effective on iOS12 or below, please wait for optimization.
If the background flashes during the disappearing of old page when popin animation shows up on Android,
the old form will have a translucent disappearing effect.
The background color of this translucent effect can be adjusted to dark color as needed. In pages.json, under globalStyle or the specified page, configure the exclusive node of app-plus, and then configure the animationAlphaBGColor attribute.
On the App side, the nvue page of uni-app is a native rendering engine based on the upgrade of weex, which realizes the native rendering capabilities of the page and improves the fluency of the page. If you have high requirements for page performance, you can use this method to develop, see: nvue.
The splash shutdown on the App side has a white screen detection mechanism. If the homepage is always blank or the homepage itself is an empty transit page, it may cause the splash to be closed for 10 seconds, which can be solved by referring to https://ask.dcloud.net.cn/article/35565(opens new window)
On the App side, when the home page is an nvue page, and set to fast startup mode(opens new window), the App startup speed is the fastest at this time.
App is set as a pure nvue project (set the renderer:"native" of app-plus in manifest), this kind of project starts faster and startup can be finished in 2 seconds. Because it uses native rendering in the entire application, instead of loading the webview-based framework.
The H5 side of uni-app comes with vue.js, vue-router and part of es6 polyfill library, and the volume of this part is only 92k after gzip, which is basically consistent with the use of vue in web development. The built-in component ui library (such as picker, switch, etc.) and js api are equivalent to a perfect large-scale ui library. But most applications will not use all built-in components and API. Therefore, uni-app provides a tree shaking optimization mechanism, the overall package volume of uni-app before tree shaking optimization is about 500k, and after the server deploys gzip, the size is 162k. The tree shake optimization needs to be configured in the manifest, details(opens new window).
The App side of uni-app is larger than the App engine of ordinary hybrid because it comes with an independent v8 engine and uni-app framework. Android basic engine is about 9M. App also provides expansion modules, such as maps, and Bluetooth. If these modules are not needed when packaging, they can be cut out to reduce the size of distribution package. You can choose it in manifest.json-App module permissions.
The App side supports that if the pure nvue project is selected (renderer:"native "under setting app-plus in manifest), the package size can be further reduced by about 2M.
App-Android side of uni-app has the concept of so library. The more so libraries that support different cpu types, the larger the package. Before HBuilderX 2.7, Android app included so libraries supported by arm32 and x86 cpu by default. The package is relatively large. If you care about size control, you can remove the support of X86 CPU in manifest (select cpu in manifest Visual Interface - Other Settings of App), which can reduce the package size to 9M. From HBuilderX 2.7+, X86 is no longer included by default. Please check it in manifest and then pack it f you need it. Most phones are generally arm-based and there are few x86 CPU scenarios, including the rare Android pad and x86 type in the as emulator.