If you use Taro to develop and feel less bugs, it means that your React code is well written . -- Team Taro
Taking advantage of the experience of doing a taro2-based micro-shop and taro2-liter taro3 project some time ago, I briefly introduced the advantages and disadvantages of Taro2 and Taro3, as well as the syntax differences in actual usage scenarios, and shared the pitfalls of Taro3 upgrade and use.
Recommended reading
exploration and practice procedures across the small end framework developed
Taro1/2
The overall architecture before Taro3 can be seen as two parts: compile time and runtime. Here's an explanation of what the two are used for:
When compiling:
Convert the code syntax by compiling the user's React code, such as jsx
to the applet xml
etc., and even convert it into code that can be run on various platforms (Tik Tok applet, WeChat applet, H5, etc.). The compile-time workflow is mainly to babel
the Taro code into an abstract syntax tree through 061efe0851f3af, and then manipulate the syntax tree to generate the code of the target platform, which is a parse -> replace -> generate
such as 061efe0851f3b1.
Take build:weapp
compile the WeChat applet as an example:
render() {
return (
<View>
{
dataList.map((data, index) => (<Text key={index}>{data.title}</Text>))
}
</View>
)
}
After babel conversion:
<view wx:for="{{dataList}}" wx:for-item="data" wx:for-index="index">
<text>{data.title}</text>
</view>
We all know that JSX is a syntax extension of JavaScript, its writing method is ever-changing and very flexible. Here we use exhaustively the possible writing methods of JSX one by one, this part is a lot of work, In fact, Taro has a large number of .
This is an excerpt from the official website's description of taro2 compilation. Due to the use of exhaustive , it is bound to cause various strange bugs of jsx and various development restrictions.
Runtime
It can be known that when we develop the taro project, we refer to the apis and components under the taro library, and call the Taro.getSettings
wx.getSettings
, in taro, we need to @taro/taro
, and then call 061efe0851f4e0, and the components are passed through @taro/components
Quote. This is because Taro has developed a set of standard component libraries and apis at runtime. By expanding the native api and cooperating with the compilation, the differences in status, event binding, page configuration and life cycle have been smoothed out, and the framework has been completed. Fit work. Specific point description:
Compiled taro code implements BaseComponent
and createComponent
, BaseComponent
role is mainly rewrite react inside render, setState and other core code, createComponent
main role is to call Component()
build pages, such as the following processing is completed docking adapter:
- Corresponds the state of the component to the data of the applet component configuration object
- Corresponding the life cycle of the component to the life cycle of the applet component
- Correspond the event handler of the component to the event handler of the applet
- ...
To put it simply, the code is first compiled into the code of each platform's structured language, and then adapted to each platform through the adapter mode and other methods to make it run. Less workload.
Summarize
- is recompiled, run lightly: This is evident from the comparison of the number of lines of code on both sides.
- The compiled code has nothing to do with React: Taro just follows React's syntax during development.
- Compiling directly with Babel: This also leads to weaknesses in engineering and plugins.
Taro3
Taro3 can be broadly understood as interpreted architecture, the work is mainly in runtime "the code interpretation", how to understand it? After upgrading to Taro, you can find that package.json
file (of course not only this one) @taro/runtime
dependencies, open the directory where the package is located:
Surprised to find us in the web only some bom
with dom
relevant keywords, the original Taro3 own implements a set of browser-like BOM / DOM that a set of API, injected into a logical layer applet through the plugin webpack , After packaging and compiling, your final code is based on BOM/DOM APIs to implement your specific functions. For example, no matter what platform, there is its own set of DOM rules for elements, and there are BOM-like ones for their respective platforms. For global api rules, what Taro3 does is to integrate the rules of these manufacturers and encapsulate them into ideas similar to BOM/DOM. All platforms are available.
Doing the most intuitive advantage is said before, no longer restricted to the framework itself , and in theory, Taro can not only support the Vue and React, also use jquery, Angular, etc. Cross-end database development . From the perspective of React users: from the development experience of taro2 and taro3, there is still a bit of the most intuitive feeling. It is more comfortable JSX
In fact, it is more friendly to support JSX
which should be logical, because taro's architecture is actually infinitely close to the React development experience, and the adaptation work is done through the runtime BOM/DOM, not like the previous version. In the same way, the writing method of JSX is adapted exhaustively
There is a key point: since Taro3 has implemented the BOM/DOM API itself, and the renderer in react, such as react-dom
, calls the browser's BOM/DOM API, then taro will definitely have its own set of rendering The reconciler is used to link the coordinator of react (reconciler, the stage of the diff algorithm) and the BOM/DOM api of taro-runtime
Source code path: @tarojs/react
, the description in the description is as follows: "like react-dom, but for mini apps."
how to choose
From the above Taro 3 architecture, the recompilation situation of Taro1/2 is changed to rerun time. In fact, the limitation of recompilation is not only a greater restriction on developers' development specifications, but also not conducive to maintenance. The source code of the taro framework, because once the manufacturers add or delete a certain specification or api of their applet, the cost of maintaining and upgrading the taro code is relatively high.
But this does not mean that taro3 must be the most suitable version. Under the same conditions, the more work done at compile time, the less work done at runtime, and the better the performance. With the progress of the times, the hardware conditions are getting better and better, and it may be a wise choice to bring a better development experience at the expense of the hardware, but for small programs that have complex logic or require more memory to run, it is still necessary to Focus on Taro2 at recompile time!
Migration guide
Before upgrading Taro Next, please read official migration guide
Convert external style withExternalStyle
In Taro1/2, you need to specify addGlobalClass
to use the external className, but Taro3 upgrades all style files to common.css, so the external style needs to be converted.
Convert hooks withHooks
All hooks in Taro1/2 and some special functional components such as Component, memo, etc. are exported from Taro. But Taro3 only maintains hooks and functional components unique to Taro, so these are split from Taro2.
Transform class component life cycle
There are some deprecated lifecycles in React that need to be prefixed with UNSAFE.
upgrade mobx4 to mobx6
If the project uses mobx, please pay attention to this rule.
The decorator is currently unstable, and the use of decorators is reduced in mobx6. Also, mobx-react is used in Taro3 instead of mobx-taro which is maintained by Taro.
Convert page configuration
Page configuration files are split out separately.
Convert route references
Access routes and route parameters using Taro3's new api.
Convert scope references withScope
Taro1/2 use the compile-time framework, Taro3 uses the runtime framework, so the scope is directly abandoned. Attempt compatibility handling in conversion.
Convert hidden attribute
A custom attribute hidden is deprecated in Taro1/2.
Modify the css of the global style to module.less
In Taro3, in order to reduce the pain points of component style files, all style files of individual scopes are upgraded to the global level. If you don't use css module after direct conversion, there will be a lot of style confusion and interference. Therefore, in order to maintain the consistency of the style, it is necessary to convert the style and convert the css into a css module.
package.json
depends on taro and extremely related dependencies are manually changed (as of 2022-01-25, the latest version of Taro 3.4.0)
{
"@tarojs/cli": "3.3.17",
"@tarojs/components": "3.3.17",
"@tarojs/react": "3.3.17",
"@tarojs/runtime": "3.3.17",
"@tarojs/taro": "3.3.17",
}
Delete the babel configuration in config/index.js in taro1/2, and add the file babel.config.js
module.exports = {
presets: [
[
'taro',
{
framework: 'react',
ts: true,
},
],
],
};
In the configuration config/index.js, specify the framework used as react
{
framework: 'react',
}
Modify the project entry file app.ts
// 修改render函数,默认render this.props.children
render() {
return this.props.children
}
// 修改导出,直接将App导出
export default App;
// Taro.render(<App />, document.getElementById('app'));
Use of native components
"Taro3's components do not have configuration files, so usingComponents must be configured in the "page" configuration file". But the components of Taro1/2 allow to declare configuration files, so in Taro3, the configuration declarations of these native components need to be promoted to refer to specific pages. See #withUsingComponentForHaicaoyun
Component Label Obsolete
In Taro1/2, the corresponding components will be compiled into components with the same name. For example, the HcyButton component is compiled into hcy-button, so if the corresponding style is defined when the style file is processed in the project, it needs to be modified manually in Taro3.
page.$component
In Taro1/2, it is allowed to access the Taro instance of the specific component by means of $component, and then you can access any method and property of the class component, and even modify its state. For example, the following example, access the instance of the previous page, and set its state
const pages = getCurrentPages();
const prevPage = pages[pages.length - 2];
const prevPageInstance = prevPage.$component;
prevPageInstance.setState({
formItems: [],
});
There is no easy replacement for this in Taro3, only a proper refactoring of all places where this part is used
Errors that may be encountered in taro2 to taro3
- Error: module "app.js" is not defined; module "common.js" is not defined (package problem of common components after subcontracting)
- webpack Parser.pp$4.raise error (DOMAIN='' used by webpack environment editor, DOMAIN='""' should be used)
- Can't resolve './style/index.scss' (taro ui2.+ and taro3.+ versions are not compatible)
- TypeError: Cannot read property 'prototype' of undefined (note that dependency references of third-party libraries cause incompatibility issues)
- MobX,Store Is Not Available, Make Sure It Is Provided By Some Provider (The entry file app.js uses <Provider {...store}></Provider>) to inject the global store
- TypeError: Cannot read property 'getBehaviorPageData' of undefined ( https://github.com/NervJS/taro/issues/7567 ) (there is no $component on the page instance obtained by Taro.getCurrentPages)
- The taro path alias needs to be configured in webpack as well
- The style is disordered. If the css module is not used in taro3, the default global style is used.
Notes on developing Taro2
Write down a few points from memory, the specific problem may also be related to the version number, for reference only
- Stateful components should be developed using class components as much as possible. Pay special attention to this point in the page. There are many bugs in hooks and some api functions in functional components, and even some hooks have bugs that are not executed.
- The element information cannot be obtained through
Taro.createSelectorQuery
in the functional component, because taro2 needs to pass the scope, but it cannot be obtained in the functional component, so useuseScope
useEffect
execution timing of 061efe0851fe22 anduseEffectLayout
is different from that of ordinary react projectsuseDidShow
does not execute on DouyinTaro.hideLoading
will be closed at the same time on the real machineTaro.showToast
- Constants cannot be exported in components. If constants are required, you need to open a separate file to export them separately.
renderItem = () => xxx
must start with render, such as 061efe0851feb8- Using switch syntax in Jsx cannot use the default branch, it will prompt you that the logic is redundant
- Try the if..else.. syntax to render nodes in jsx, sometimes it is not as you want, try to define a variable node, assign it to node in the branch, and finally return the node node to solve the problem
- If mobx is used,
toJS
needs to package it with 061efe0851ff20 when jsx conditional rendering, such as:toJS(list).length > 0 && <View>xxx</View>
Swiper
assemblynextMargin
andpreviousMargin
properties invalid terminal h5- h5 Sometimes the height of the container will be higher than that of the applet, you need to set
box-sizing: border-box;
- If the
View
andText
tag selectors are not used, they will not take effect in H5. Solution: use className
Notes on developing Taro3
Write down a few points from memory, the specific problem may also be related to the version number, for reference only
Updating components will re-render sibling nodes, problem description
Solution: add layers to sibling nodes or itself
- Use
Taro.createAnimation
,animationData
initial value can not benull
, otherwise excessive animation effect will fail, rendering the final direct style, can be used to solve this problem{}
- Before version 3.4.0
Taro.createAnimation
on H5 side - For rendering problems caused by too deep layers, you can try to use the
CustomWrapper
component package, which is used to create a native custom component. Descendent nodes of thesetData
thus call custom components, achieve the effect of partial update , so as to enhance the performance of the update. - Sometimes the video component cannot get the duration when it is rendered for the first time, and it cannot be played automatically.
- Pseudo elements and pseudo classes are invalid on the applet side
- Global style problem, if it is not a css module in taro3, the default style file affects all components
Image
in h5 has a layer of packaging, which also exists in taro2ScrollView
inposition: sticky
invalid, this also exists in taro2- Hidden exception, through
state
data control display and hide, will not take effect. Solution: Solve by trinocular operation
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。