preface
In early July, I had the honor to attend the GMTC Beijing 2021 Small Program Development Practice special session. I listened to four speech topics, which were:
- Jingxi cross-end applets development practice
- Intelligent generation of cloud integrated code, improve the efficiency of small program development
- Didi Chuxing’s complex small program solution based on Mpx
- Forge ahead – Tiktok small program front-end rendering framework evolution
After listening to the intensive afternoon of sharing, I feel that the amount of information is still relatively large, which leads to a lot of thinking, so I will slowly talk about it.
Jingxi cross-end applets development practice
The first session was shared by the front-end engineer of Jingxi products under JINGdong. The theme was about small programs and H5 cross-end development. Coincidentally, we are doing similar things now, so WE listened to this session very carefully.
Project background
Jingxi, as a social e-commerce product of JINGdong (pinduoduo), has gained access to wechat’s “Discover Page” traffic, so its business volume is relatively large:
- The volume of the whole package is 20M
- 100+ developers, with different teams
- Peak hundred million requests
- Across multiple ends: applets for multiple platforms + H5 in multiple containers
Across the practice
The Beijing xi small programs across end based on jingdong since the research framework of Taro, more worthy of attention is jing xi due to the large volume, problems left over by history, each page is a warehouse, can be compiled on a single page full development, debugging, single page build will eventually merge again after the completion of building to the whole project, equivalent to do the second build. In addition, for this framework, the whole Beijing xi small program there are a variety of technology stack.
In the cross-terminal syntax section, the cross-terminal development capabilities based on Taro can be found at taro-docs.jd.com/taro/docs/e… , will not be repeated here:
- Built-in environment variables
- Conditional compilation
- Multiterminal file suffixes
Home Page Performance Optimization
The lecturer experienced the home page performance optimization project and achieved certain results. Before this, The home page of Jingxi faced some performance bottlenecks, such as low end machine not smooth, machine heating and other problems.
Home performance optimization from three points to do: virtual list, low-end machine degradation, experience scoring.
Virtual list
The landing scene of the virtual list is the commodity list on the home page. The commodity list is characterized by a long list and complex functions, which leads to the lag after scrolling two screens, so the landing of the virtual list is made:
- Structure transformation
A common scenario for virtual lists is a long list of entire pages, but this is special because instead of the entire page being a list, only parts of the page are included. Therefore, the component itself is not very good to listen for the scroll event of the page, and can only be passed in from the component based on the event center of Taro.
- Card height calculation
One of the characteristics of commodity cards is variable height, the intuitive idea is to obtain the card DOM height through the DOM API, but there is a problem here is that the DOM API in the small program (SelectorQuery) performance is not good, in such a list scenario to call a large number of more likely to encounter performance problems.
Since the DOM API is not an option, you can start with the business and find that the height of the card can be calculated from the content by adding up the heights of the components. The idea worked and performed well, but there was one small problem: The height calculated by the small program was inconsistent with the actual DOM height. After investigation, it was found that the height did not meet expectations due to the RPX conversion rules. 1RPX would be converted to 0.42px when drawing, but 0.426667px when calculating. The solution is also very simple, computing logic for the small program platform to do a distinction.
- White during optimization
As for the white screen optimization is relatively simple, is a common skeleton diagram, here will not repeat.
Low-end downgrade
Low-end machine downgrade is the first division standard, here at the beginning of the research and development of a standard, according to the year, system, time to market to determine whether it is high/low-end machine. But after landing, I found that the standard of high-end machines was set low, some high-end machines would also lag, and the proportion of high-end machines and the proportion of users in product channels did not meet. After recalibrating the parameters, about 2/3 are high-end machines and 1/3 are low-end + unknown, which is more consistent with the fact.
In the clear low-end machine standard, for the low-end machine can do some optimization:
- Carousel chart to single chart
- GIF to static
- Change the big picture to the small picture
- Remove cross-module/time associations (simplify logic such as popovers)
Experience rating
The applets IDE comes with an experience score, which consists of the following metrics:
- Number of FIRST-screen DOM (set to 1000)
- Image size
- SetData call frequency and content size
Jingxi for these optimization items, the experience of the score to achieve the full 100 points.
Code volume optimization
Small programs have a package size limit, beyond which the version cannot be issued, so you need to optimize the code size.
Common ways to gain more:
- The subcontract
- Rely on analysis to remove unused content
- Avoid using local resources, especially images
- All types are compressed and comment cleaned
In addition, Jingxi home page has also made some more refined optimization for CSS:
- Inherited attributes:
Some CSS properties can be defined globally, such as color line-height font-family font-size and @font-face. Here the lecturer gives an example of @font-face being redefined 231 times in their home page project. After this series of optimization, the module volume of the home page is reduced by 10K, accounting for 1.6% of the total project amount of 630K.
- Style completion:
For example, display: flex is often used to add a line display: -webkit-flex to the final page in various ways to support multiple hosting environments.
In the small program IDE, select style auto-completion is supported when uploading code, and of course the framework is also completed at compile time via PostCSS. So which one to choose? After the comparison attempt of Jingxi, it is found that the completion of small program IDE has no problem in use, and it can also avoid the style completion code added by PostCSS compilation into the volume of small program, so the framework completion is finally closed, and the small program IDE completion is selected, which reduces the package volume by 58K. Accounting for 9% of the project total of 630K.
- Style naming optimization
UglifyJS can simplify function names to a, B and c during compilation of JS code; Similarly, we can optimize the classname within the component.
By default, CSS and JSX are separated, making it difficult to associate classnames in JSX with classnames in CSS. It can be done, but it’s a bit of a hassle.
So Jingxi chose CSS Module to establish style and JS association:
After this optimization, the volume is reduced by another 50K, accounting for 7.9% of the total project amount of 630K.
This series of optimizations reduced the size from 631K to 465K, which is significant in the context of the small package size.
System monitoring
Jingxi small program uses Badjs to collect quality data, but it will encounter some problems, such as large quantity of online quality data, unclear module division and little real-time feedback information. Therefore, a number of availability monitoring platforms have been established to coordinate with data to establish sequential and year-on-year rules for alarm processing.
Q&A session
- Why use Taro on the homepage and other pages can use other technology stacks
- The home page is the experimental field, other businesses will have their own selection or historical legacy problems
- Compile only the home page to avoid other service impacts
- What page on the scorecard is rated better by applets, according to the source
- Refer to Google Chrome
- Gray level strategy
- Developer grayscale experience pack
- The accelerated step by step
thinking
business
This speech is to share from a business perspective. Currently, we are mainly promoting a multi-terminal (H5 in wechat and wechat mini program) product with multiple business modules. Jingxi’s sharing has pointed out some future development paths for us.
Across the
In terms of cross-end practice, Taro provides a way that is good enough for us to do multi-end development and debugging, as well as code maintenance.
Although the cost of learning Taro cross-terminal development is very low, there is still a short adaptation period, especially after new students join the Taro cross-terminal development. In the early days, when there are not many people, we often try to avoid code that does not conform to cross-terminal best practices into the final Codebase during the CodeReview phase, but now the team size is gradually increasing. We tried to use Linter Plugin to precipitate our cross-side experience accumulated in the past CodeReview, which has been initially implemented in the project, and has indeed been effective. According to the CodeReview data, the cross-side grammar problems have decreased by 90+% after the implementation. We’ll share more details about this future.
Therefore, in this point, we can be more confident that we do better than Beijing Xi, at least our CodeReview is more strict, there is no Beijing Xi home page module repeatedly defined 200+ times font file such a problem. We will continue to iterate on the Linter Plugin in the future, putting more practice into it and killing problems in the process of writing code.
build
In terms of small package size, we are already about to exceed the 2M limit for single package size. This piece of Jingxi shows us a way, which is also a point of interest to everyone in the Q&A session. Jingxi has done similar splitting work of the client team in construction.
Giant apps such as Toutiao, Tiktok and Alipay, which contain multiple business logic, are often developed across teams. It is definitely unrealistic to start all the modules of the entire App during development, so they generally develop and build the functional modules of the App independently. Jingxi small program should divide the project into multiple independent subcontracts, so it can realize the independent development and construction of a single module, and finally combine each module to build a output of the final small program.
Different from The independent cross-ends of each page of Jingxi, each page of H5 application is separated. Our whole application also provides SPA in the form of H5, so we cannot completely copy the construction experience of Jingxi. In the second half of the year, we will focus on exploring the Taro framework to perfectly support the construction of cross-end sub-warehouses to improve the development experience and efficiency.
performance
In the first half of this year, we experienced a process from scratch in business, and the volume of business has just exploded in recent months. Therefore, in the past half year, we mainly made technical planning from the perspective of R&D and efficiency improvement, and did not encounter major problems in performance, so we did not pay special attention to performance data. It is expected that after the business is stable in the second half of the year, we will do some optimization work in terms of performance. Jingxi’s experience will be our key reference material, such as low-end machine degradation.
monitoring
Small programs are like Web, but also like App. Currently, the end-to-end monitoring within Bytedance for small programs is not perfect, and many monitoring indicators are missing compared with Web + App. Basic monitoring and alerting is fine, but it’s hard to detail the data. In the second half of this year, we will try to accumulate some experience of cross-end performance optimization in the performance optimization work, and help the end monitoring to improve this area.
conclusion
This sharing was the one closest to business development, and also the one that triggered my thinking the most. After the meeting, I had some simple communication with the lecturer and added the lecturer’s wechat account. I will also have further technical communication with the lecturer to learn more experience from the business team.
Intelligent generation of cloud integrated code, improve the efficiency of small program development
This session was shared by CTO of DCloud, mainly about PaaS related content of small program.
Front/back end collaborative mode evolution
The lecturer divided the front and back end collaboration mode into several stages:
- The first stage: 1990~2005, after the birth of HTML, the page is mainly by ASP/JSP/PHP template prologue realization of dynamic web page + JS + CSS composition
- The second stage: from 2005 to 2018, the emergence of AJAX and the maturity of mobile Internet make each end become a big front-end together. WebApp, native App and small program provide better user experience, but the development efficiency is relatively low. At this stage, cross-endpoints gradually become the mainstream, such as ReactNative, Weex, Taro, Uni-App, Flutter and other technology solutions, cross-H5, iOS, Android, small application multi-terminal.
- The third stage: from 2018 to today, the emergence of Serverless enables developers to operate databases directly on the end without building servers, which improves the development efficiency while ensuring user experience. It has evolved into a structure that emphasizes front-end and light back-end, with business logic migration and front-end assuming more responsibilities.
The advancement and limitation of small program cloud development
- Table level permissions, scenarios are limited, slightly more complex rules can not be done
- Only registered users with more than 50 points can comment on an article
- Only the administrator can set up the essence, the amount of reading system increased
- Parameter legal: when the library is difficult to do data verification
- Data fragmentation: small program vendor support and standards are different, using more than one cloud will lead to data scattered in each cloud database, it is difficult to count together
UniCloud improvement exploration
- Cross Cloud: uniCloud SDK + UNI-app Runtime
- Specification formulation: with the help of JSON Schema to support permission configuration, field verification and component binding, a SET of DSL is designed to do permission control and field verification
- ClientDB Cloud integration: front-end DB SDK + data components
Intelligent Generation of small program code
Most of you have been exposed to similar LowCode solutions, but I won’t go into details here, just post a picture, and you can see more on the PPT.
The wheel ecology of the future
At present, the separation of front and rear ends leads to the ecological separation of front and rear wheels, and there is a large gully between the front frame and rear frame; In the context of more and more responsibilities on the front end, the future may move towards cloud integration.
However, although the current cloud development is highly efficient, it has great limitations and is difficult to meet the requirements of complex business. The future direction of exploration includes two directions: better support for complex business scenarios (cross-cloud cross-terminal, refined permissions, strict field verification, front-end data components) and the idea of code generation based on cloud development mode.
Q&A session
- Cloud MongoDB database may be a low version does not support transactions, so how to implement transactions
- Cloud vendor version Select a higher version
- The cloud does transactions, the front end does not
thinking
Note that DCloud is also the open source uni-App company. Uni-app + uniCloud is the development direction of cloud integration, which is the best solution for DCloud, a PaaS cloud service manufacturer.
In this part because I have not paid much attention to, also have no landing experience, so I will not present the ugly. The best team in the company to do this would be The Light Service, and the way light service and uniCloud SDK are used is very similar, except that light service is in Web architecture and uniCloud is in applets architecture.
Didi Chuxing’s complex small program solution based on Mpx
In this session, Didi’s senior expert engineers shared their open source Mpx applet framework.
Introduction to the complexity of Didi Chuxing mini program
- Complex business logic (multi-scene/multi-state/heavy map)
- Huge business volume (18+ business lines/marketing business closed loop/total package volume 20M)
- Cross-team development (10+ business teams)
- Release across multiple terminals (wechat/Alipay /QQ/ byte /Web)
- Multi-language support (support Switching between Chinese and English)
An overview of the Mpx applets framework
Small program first enhanced cross-end development framework
Different from the mainstream applets framework in the industry that pursues the React/Vue Web MVVM framework running in the applets environment, Mpx is based on the native syntax and technical capabilities of applets, referring to the excellent syntax design of the Vue framework, and enhancing and extending it through compilation and runtime means. Allows users to develop applets in a way that approximates the Vue experience while maintaining the same or better performance and package size as native applets.
Industry applet framework similarities and Differences – performance versus efficiency trade-offs
The two most common framework types in the industry are statically compiled and dynamically rendered:
-
Statically compiled versions are represented by UNI-app and Taro2:
- Uni-app is Vue and Taro2 is React
- The technical solution is recompile time, which compiles Vue/React directly to the applet native
- The advantage is that the performance is better, because the compiled code is close to the native written small program; And can have the Web migration capability
- The disadvantages are also obvious, as Web frameworks are limited by their ability to compile, such as the JSX loop in Taro2, which is very limited and prone to writing bugs
-
Dynamic rendering, runtime framework, a current trend, represented by Taro3:
- The DSL layer is free to use any Web framework
- The technical solution is to re-run, with the help of recursive dynamic templates to simulate the DOM environment, so you can directly run the Vue/React view layer framework directly on the small program
- The advantages are the opposite of statically compiled: the use of the Web framework is unrestricted, and almost any syntax is freely available, making it easy to migrate the Web
- The disadvantages are also the opposite of statically compiled: performance is relatively poor, and setData is relatively expensive to send data and to render
These two implementations can also be a bit cumbersome to use some of the native features of applets because they do applets on the Web.
Mpx went the third way, native and enhanced:
- DSL layer based on the syntax of the applets to do extension, because the syntax itself is similar to Vue, so the extension is vUe-like syntax, so compile
- The technical solution is similar to Vue2, compile + runtime
- The advantage is that the performance can be excellent, because Vue can do AOT at compile time, and has refined dependency tracking at run time, so it can ensure that the fine-grained update of setData is almost optimal; At the same time because it is a small program grammar expansion, so and native small program development experience is relatively close, the use of native grammar is not very troublesome
- Disadvantages are too close to the small program, not a complete Vue, Web migration ability is weak
The bottom line is that Mpx was designed to trade off some of the efficiency of Web development for more efficient applets.
Mpx global architecture
Similar to common frameworks in the industry, there is a compilation layer and a runtime. The compilation layer is completely based on Webpack, and the compilation is realized by deeply customized Webpack Plugin. At run time, the core module includes applets platform difference smoothing, responsive logic, and some peripheral libraries such as Mock.
Overview of Mpx support capabilities
-
Development experience and efficiency
- Data response
- Across the development
- Template instruction enhancement
- CSS pretreatment
- ES6 + support
- TypeScript support
- I18n support
-
Quality and performance
- SetData optimization
- According to the need to build
- Subcontracted resource handling
- Package volume optimization
- Package volume analysis
- Unit test support
- SourceMap support
-
Cross-team development
- NPM support
- Multiple instance Store
- Packages specification
- Native progressive migration
Mpx usage
Mpx supports almost all of Didi’s internal applets, such as Didi, Qingju and Orange Heart, and has been awarded 2.8K Stars on GitHub.
Data response and performance optimization
Data response programming
The vUe-like syntax is not repeated here.
Mpx data response implementation
Mpx refers to the implementation of Vue2 and realizes data responsiveness based on defineProperty. The difference between Vue and Vue is that as a Web platform, Vue can directly operate DOM and ultimately drive DOM changes after data changes. However, DOM cannot be manipulated directly in the applet, so the setData of the applet is driven after data changes in Mpx, and the applet is responsible for rendering.
In the future, when the applet host environment compatibility becomes better, Mpx will also consider changing to Vue3 Proxy for implementation.
SetData optimization under data response
The small program setData performance optimization suggestions are generally three: avoid setData data is too large, avoid setData calls too frequently, and avoid the template in the unbound data into setData.
There are three general implementations of the framework:
- Full Settings: pass in the data corresponding to the entire template, which is the simplest and the worst performance
- Deep diff Settings: Make a deep diff for the data of the last and this time, and conduct incremental setData. This implementation can avoid the setData data being too large and frequently called, but it cannot avoid passing in unused data, because in this case, the data is not associated with the template. I don’t know which part of the template really needs data
- Set only the minimum amount of data that is used and changed on the template: this is the Mpx approach, and it is the best implementation
SetData optimization scheme based on render function
In Vue, BY relying on collection and tracking, Vue can finally achieve refined DOM update. Similarly, in Mpx, by relying on collection and tracking, data changes can be associated with setData to achieve refined setData update.
Mpx can also merge renderings using Nexttick just like Vue.
Render function generation process
The first compilation compiles the template to the original rendering function, but the original rendering function cannot be used directly at runtime, so a second compilation is made based on Babel to remove the this context so that it can be used directly at runtime later.
Mpx setData optimization effect
In didi’s Mpx projects, setData optimization has not been done manually, but the performance has been excellent. Mpx also performs best in the Benchmark scenario.
Compile build and package volume optimization
Mpx builds
Because Mpx builds based on Webpack, the entire dependency analysis, build and build process is similar to a normal Vue project.
Applets resource dependency tree
Json page. Json describes resource dependencies, which can be used to do dependency analysis.
NPM support
Wechat applet official NPM support is poor, there are many problems, such as full copy of NPM package, Mpx optimization, to solve these problems.
The subcontract to build
The main package and individual subpackages are built sequentially based on the user subcontracting configuration. The SplitChunksPlugin configuration is also automatically generated to export the common modules in the project to the main package or subbundle.
Independent subcontracting is also supported. Independent subcontracting can run without the main package, so in the case of independent subcontracting, independent runtime and related resources will be given to ensure that it can run independently.
Small package volume analysis
In the Webpack ecosystem, package volume analysis tools are designed for the Web and have some disadvantages in the small program scenario. Take Webpack-bundle-Analyzer as an example:
- Only the js module volume can be analyzed statistically, and the applets output contains a large number of non-JS resources
- Since there is no subcontracting concept in the Web system, it is impossible to conduct statistical analysis of volume in the subcontracting dimension, but the volume limit of the small program is set on each subcontracting
- Volume is difficult to trace
To address these issues, Mpx has a built-in package volume analysis tool that supports the following features:
- Total resources (JS and non-JS) volume statistical analysis
- Support volume statistical analysis by subcontracting dimension
- Supports volume statistical analysis by source configuration group
- You can configure volume thresholds for volume control based on the grouping and subcontracting dimensions
In didi’s business scenario, each business side will develop in a small program, so it is very important to analyze the volume of each business.
Therefore, Mpx packet volume analysis sets the concept of entry and groups packets according to entry. We then do a depth-first traverse of the entire dependency tree, starting with app.json, and categorize their resource size information by group. If the resource is used by the group, it is the group’s self size, otherwise, it is shared size. In addition, Didi has created a set of visual pages to show the data from its bread volume analysis.
Applets cross – end
Mpx 1.0 has been enhanced for various platforms. In 2.0, it takes wechat mini program as the standard, and supports alipay, Baidu and other mini program platforms through the framework for cross-platform conversion.
In the design and implementation, the static part is mainly done by compilation and transformation, and the dynamic part is mainly smoothed by runtime. The conditional compilation capability is provided for the differences that cannot be handled by the framework. This is similar to Taro and other frameworks.
- Conditional compilation of file dimensions, identifying platforms by file suffixes, for example
card.wx.mpx
card.ali.mpx
- Block dimension conditional compilation. In a single file component, the script tag can be configured with the mode attribute to specify that the logic is suitable for a particular platform
- Conditional compilation of code dimensions, using environment variables to distinguish if else, and support the removal of conditional dead branches at compile time
- Attribute dimension conditional compilation. When platform differences only exist in node attribute dimension, the use of code dimension conditional compilation is redundant and difficult to maintain subtrees:
<view class@wx="wx-container" class@ali="ali-container"></view>
In terms of the output Web platform, the syntax is borrowed from Vue, so it is mainly implemented based on Vue. Implementations of basic applets such as page routing capabilities are injected at compile time. In the component part, Mpx directly changes tags such as View and text into basic components in HTML. For example, VIEW is replaced by div.
Mpx multilingual support
As the small program is dual-threaded architecture, setData data transmission should be reduced as much as possible, so there are two Mpx I18N schemes. One is WXS mode, which puts multi-language documents in the template. This scheme has no extra communication overhead and good performance, but the problem is that it will lead to packet volume increase. The language bundle exists in both WXS and JS, and because the copy is determined at compile time, it cannot be loaded asynchronously later; The other scheme is computed mode, which has the opposite advantages and disadvantages compared with WXS mode. The communication cost is high, but the packet volume occupation is small, and the language package can be loaded asynchronously.
Outlook and Future
- Webpack5 construction upgrade, greatly improve the construction speed
- Vue3 data response upgrade supports composition API
- Unit testing is further improved with full support for Jest Mock
- E2E automated test support
- The MX-Cube-UI cross-end component library is open source
- Support local component runtime rendering
Q&A session
Sorry, I don’t remember much here.
thinking
Before sharing my thoughts, I would like to declare that I am a Vue Contributor & Taro Contributor, so I do not guarantee that the following content will not be mixed with illicit goods.
To be honest, I was a little disappointed at the beginning. I expected to talk about didi Chuxing’s small program practice from the perspective of business landing, which was similar to the first session, but it turned into a pure Mpx technical details sharing within a few minutes. Pure technical details are more suitable to be shared in the form of an article. It is easy for the audience to follow the ideas provided in the form of a speech. Fortunately, THE PPT content is relatively detailed, but it is not too big a problem.
After listening to the whole sharing, ALTHOUGH I still wouldn’t choose Mpx according to our business background and the background of other students in the team, some work of Mpx also gave us some directions for the future, so it was not a waste of listening.
Small program framework design ramble
Although there are many comments on the design of small program framework in the industry, I still want to talk about it.
With the development of Web, HTML, CSS and JS have basically become a fact assembly language. As long as it is to build a page application with a certain complexity, almost no one will take the Three Muskers to write from scratch, and everyone will choose a Web framework like Vue and React.
Small program design of the three musketeers in the Vue though and very similar, but become reality or not escape the fate of the assembly language, the reasoning behind this is, of course, a lot of, the rationality of the design of the DSL aside, the programmer is always lazy, if can use familiar Web framework to develop, and who are willing to learn a new grammar? This is also the background for the emergence of mini program frameworks such as Uni-App and Taro. Even wechat mini program officials are recommending frameworks such as Kbone.
Recompiled framework
In the first generation of applets, the idea was that since the applets syntax was similar to Vue and React, we should simply compile Vue and React into applets.
The most direct problem of this scheme is that the syntax of Vue and React is targeted at the Web platform, and many applications in small programs will be limited. For example, mpVue, represented by the syntax of Vue, cannot use complex JS expressions. The complex map loop cannot be used in JSX in Taro 1/2, as represented by React.
In simple scenarios, Vue template and React JSX can be equally compiled into small program templates. However, the workload of supporting complex syntax is very explosive. In particular, JSX flexibility is JS. Compiling standard JSX to template is almost as much AOT work as JS.
There is a framework called solid. Js that does AOT for JSX, but of course its JSX syntax is limited. Interested students can read the documentation for themselves.
In this type of framework, the resulting small program code is very similar to the original Vue and React code, and the natural performance is very close to the small program native.
Rerun the runtime framework
What if you don’t want to use the restricted Web framework syntax anymore, but the applet doesn’t want to touch the DOM directly?
This is when someone genius discovered the technique of “dynamic recursive templates”. I won’t go back to who came up with it, but it’s interesting in itself, so let’s talk about it.
Applets often support recursive template references, such as nested views inside dynamic views with this pseudo-code:
<template name="view">
<block a:for="{{item.children}}" key="{{item.id}}">
<template is="view" data="{{item: item}}" />
</block>
</template>
Copy the code
So someone thought, can we make a universal template, this universal template can describe all pages, template and JS data is VDOM AST?
If you have a project that uses Taro3, you can take a look at the compiled product directory. Base. WXML is the universal template, and AppData in the small program IDE is the AST of the page:
This is comfortable enough to simulate all DOM operations.
This scheme many people will say that the performance is not good, here is also a detailed talk, why the performance is not good:
- Data is the AST of the page, and small program is the double thread model, divided into logic and rendering layer (detailed can read this series of articles zhaomenghuan.js.org/blog/wechat…). It is this model that restricts DOM manipulation, allowing only serializable page data from the logical layer to the rendering layer, known as setData in the applet. As you all know, communication between threads is expensive, so the larger the data, the more expensive the data. Although this implementation can do merge updates, but data contains the AST, data size must not be small.
- I don’t care if I have to go to that many nodes,
base.xml
It’s always that big, just like the starting price of a taxi. For lightweight scenarios, this is a disadvantage, and this template is already 63K.
In summary, especially in the Benchmark scenario, dynamic template frameworks are hardly superior to recompiled frameworks.
Note, however, that business is often different from Benchmark, and few people outside framework developers and novices write Todo MVC. Although the dynamic template solution has a starting price, if you look at the template files compiled for each page, you will find that they are directly referenced to base.xml. The cost of adding a new page template is almost zero (and can be compressed by Gzip when packaging). So as long as you reach a certain threshold of page complexity and number, the size disadvantage can turn into an advantage, as our product currently has almost hundreds of pages and a large number of components, and the size of the run-time framework selected is not necessarily worse than the compiled framework.
Talk about Mpx
I’m not going to comment on Mpx here, after all, they’ve already said that it was designed for their business background, they have some native small applications, Mpx as an enhanced framework, migration costs are certainly less than the first two, but I can hardly call it a third generation framework.
There are two main things Mpx gives us to think about:
One is that the business context should be taken into account when building wheels, which is something the lecturer emphasized as a core Mpx developer.
Last year, our team made a Node.js framework called RingJS and successfully implemented it (we will talk about this in more detail in the future). One of the important points is that RingJS has very low migration cost in the background of our bare Koa Node.js applications. If we force a framework like Nest.js into use, either the migration workload will explode or it will never land.
Second, in the market, there are already several frameworks occupying almost all the market, how can we find the positioning of our own framework?
In the Web world is the React, Vue, presents three framework hogging all the market, especially the rain creek was in zhihu an answer (see www.zhihu.com/question/33)… “How do you push a new framework when the big three have almost taken over the market? Look at what Rich Harris did with Svelte 3.”
Similarly, GitHub Star’s compilation frameworks uni-App, MPvue, Taro 1/2, and Taro3 in the redo runtime framework have taken over the market for almost all small application frameworks, making another MPvue or Taro3 doesn’t make sense. You can’t convince users to use your framework instead of using an existing framework that is better known, stable, and eco-friendly.
I feel that Mpx has found a good point in this regard. Like Svelte, Mpx will attract some of the developers who used to be native applets to give Mpx a try in terms of performance, lightweight, close syntax to Vue, and enhanced design to reduce the cost of learning and landing.
Package volume analysis
The limitations of package volume analysis tools mentioned in Mpx are actually found in various frameworks, such as Taro, etc. In the following performance optimization work, if we can have a package volume analysis tool supporting Taro, it will be more successful. Complementing Taro ecology’s package volume analysis tools will become an important part of our performance optimization efforts. At present, we have preliminarily produced output in this area, and we will share relevant information in the future.
conclusion
Even though Mpx didn’t fit our business scenario and context, there were a lot of things that Mpx tried to do that got us thinking and inspired.
Douyin small program front-end rendering framework
The last session is shared by our byte classmates, mainly from the internal perspective of small program manufacturers. Interestingly, the lecturer just went to Shenzhen on a business trip, so he was still in home isolation at that time and was remotely connected.
In addition, the lecturer is also a good friend of mine, and I have had a lot of technical exchanges in private. I have talked about part of the background and content of the speech before, so it sounds relatively relaxed.
Small program rendering background introduction
What is tiktok applet?
There is no need to introduce it here. At present, many businesses have been connected, including education, such as Guagualong and Qingbei.
Applets runtime architecture
First, the bottom layer is access to host App, providing small program running environment and management ability; On top of this is the Native runtime, which can be common Android and iOS, or IoT devices that provide page stack and side capabilities; Above is the cross-terminal channel, supporting multi-terminal communication; At the top is the JSSDK, the JS runtime for small programs that provides components, apis, rendering, and other core capabilities, which we’ll focus on next.
Applets run the flow
The user’s applets will go through four steps to be run:
- Compilation: The applet code goes through a layer of escape, into code that the JS engine can recognize, and is packaged
- Deliver: Delivers the applet when it is opened by the end
- Load: After delivery, the end loads the applets
- Run: the small program starts to run after loading
The next step is to compile and run the two processes.
Applet rendering background
Small program rendering to serve both internal and external developers, internal mainly view, text and other built-in components rendering, external developers need to use in the page, such as custom components rendering, the two are very close, but the appeal is not the same, in some aspects are completely opposite.
Internally, performance is more important, and designs with a high level of abstraction are generally unacceptable because of the higher overhead associated with abstraction. Internal needs to be more in touch with the bottom and the essence, the learning cost of development will be higher.
For external developers:
- The small program syntax consistency requirements are relatively high, not because of a platform and rendering framework, to learn and develop again
- The two-thread rendering model of small programs determines that the data communicated between threads must be serializable, so ideas like Proxy and Observable are not feasible
- There are performance requirements
- Testability is also required
In summary, developers will focus on the limitations of development and the cost of learning, and will not accept higher learning costs. Based on the above background, the rendering framework of the first version of the applet was designed with two separate sets of components.
Such a separate scheme brought some early benefits:
- Abstractions are different and can be developed in parallel
- Separate designs and implementations make it easier to test separately
But such a separation could create more problems. As shown in the figure, the internal components are Web components based on Polymer implementation, which use native events to avoid the overhead brought by synthetic events, and use DOM life cycle to complete the component life cycle. Custom components are completely different because of the need for high customization, so vDOM-based solutions do components, events are composite events, and life cycles support custom life cycles.
Such a separated scheme brings a lot of problems to the subsequent development and maintenance. For example, when both ends need to do some development work, the developer of the rendering layer must maintain two sets at the same time, and ensure that the two sides are equal; Developers who rely on both internal and external components may also find the lifecycle misaligned.
In view of these problems, a unified componentization mechanism is needed to unify the two.
Frame design and thinking
Why not use XXX?
Why not use existing open source solutions like React, Vue, and Svelte? Because the application scenarios are different.
The current appeal is:
- Light weight, pluggable
- Independent drawing: small programs have multiple platforms, to provide a unified solution for multiple platforms
React seems to satisfy both requirements. React also supports Custom Render, but Fiber and Concurrent Mode have been complicated and heavy since 16, and the React code is not easy to understand. In the industry, Alipay uses React, which is now more difficult to maintain, and is not aligned with wechat in details.
- Highly customizable: You don’t want to go around patching
- Performance optimization space: Similar to point 3
According to these four points, it is difficult for existing schemes to fully meet the existing needs, so I think I need to make a set of frameworks myself.
Frame design myth
The design of the framework needs to see the scene and requirements, here from three points of view of the framework design:
- Capability provision: What capability does the framework provide, component abstraction? Pluggable render API?
- Rendering mechanism: JSX vs Template is the current mainstream, both have their advantages and disadvantages, but the current industry trend is towards static direction, template can provide some information in a fixed scene, easy to do AOT
-
State management: There are many industry solutions
-
Changes to monitor
- defineProperty / Proxy
- DefineProperty has a bug with array listening
- The compatibility of Proxy on the C end is not guaranteed and may not be supported on the C end
- defineProperty / Proxy
-
set-data
- For example, the React setState can only go through the data diff and does not know the exact page update location
-
Streaming updates
- For example, Cyclejs, streaming updates can achieve accurate updates, but because JS native does not support lazy eval (lazy evaluation), it generally relies on closure implementation. Although this implementation in JS has good performance, it is under heavy memory pressure, which limits device performance in IoT scenarios
-
Changes to find
- Svelte, for example, uses fixed template syntax. The problem with this scheme is that the source code and compiled code differ greatly, making debugging more difficult
-
Our choice
For the required features, all: progressive compilation optimization + set-data + runtime configuration.
In the case of external development capabilities, the template of the page is compiled into the Render function and interpolated in the render function for performance optimization, and the final external component will call the render function for rendering.
Internally, native components are described by JSX. Templates are not used here because internal components have a lot of dependence on VDOM. For example, Swiper components need to have SwiperItem inside, and it is difficult to verify templates if you use templates.
Render Optimization Tips
ChildFlag
Structural stability is important for performance optimization, as shown in the figure below. The first part of hello is clearly fixed to a string node, and the second part switches between Boolean and VNode.
Before React would only memorize such scenarios by typeof constantly at runtime, which brought great pressure to the runtime. Now React will memorize nodes according to such scenarios, which is similar to hidden Class optimization in V8. If the passed argument is stable, V8 will skip validation of the argument and run it directly.
By adding various identifiers to nodes, the online diff pressure is reduced by 70%, which is a threefold increase in diFF performance:
Of course, such identifiers are not practical for users to write by hand, but since compile-time exists, identifiers can be added automatically at compile time.
VNode Immutability
The code in the figure, for example, marks children as an immutable node if they remain unchanged, so that it can be skipped in subsequent diff to reduce diff work.
In addition to these optimizations, a number of optimizations, such as V8 core dump, were made to see if performance deteriorated.
Benchmark
Of course, there is no proof, but also the corresponding benchmark to prove. The name of yaW, which stands for Yet Another Web-Component, is the front end rendering framework of benchmark.
Yaw still has an unlaunched optimized version, in which vuE-Next and Svelte have made PatchFlag and other optimizations. It was not launched because it was found that this feature would destroy the VNode structure and lead to the fragmentation of VNode. Vue can do this because Vue doesn’t have a lot of dependencies on VNode operations. I won’t go into that here.
Performance tools and tuning
There are three tools. The first is the client performance analysis tool. On the client, you can open the performance analysis tool and view the actual CPU and memory usage. The second is the IDE performance Trace tool, which provides a fine-grained view of performance data. The third is the IDE performance scoring tool, which gives you a rough look at performance optimization points. The detailed comparison of the three tools is as follows:
thinking
This sharing is more inside-out, showing the internal details of applets manufacturers, so that external developers can understand their design and implementation.
If you are interested in the design and implementation of each Web front-end framework, you should have a better understanding of the framework design part, if you do not understand it does not matter, the core point of the lecturer is very good, you can study more PPT.
In terms of rendering optimization skills, if you pay more attention to Vue3, you will find that many optimization skills in YaW are similar to Vue3. The key idea is to skip fixed parts. Do more intensification of update (see VueConf 2019 SH especially rain creek share img.w3ctech.com/VueConf2019…) .
Written in the end
Finally, I would like to thank the company for giving me this opportunity to go to GMTC 2021. Here, I will summarize what I have seen and thought in a written form. I hope that you can gain as much as I do, and welcome you to further exchange and share with me.