欢迎转载,请支持原创,保留原文链接:blog.ilibrary.me

Taro 3出来有段时间了,有一个小程序用Taro 2写的,升级了一下,前前后后花了几个月时间,中间还失败了几次,踩了不少坑。

最主要的问题还是这类工具文档相对缺乏,很多时候只能摸瞎,碰运气解决问题。

本文主要记录踩坑记录,分享个人的踩坑经历,让踩同样的坑的人能快速绕过同样的坑,并不是一篇系统性的解释taro原理或者新老taro版本对比的文章,也不对Taro升级做完整的解释。

怎么读这篇文章:

  1. 文章重点分两部分,第一部分是升级流程, 相当于升级教程。 第二部分是问题流水账, 相当于问题解决手册,遇到具体的错误可以直接查阅这地方的内容。
  2. 升级前建议按照升级流程把里面的每一步都做一遍,出问题也没关系。做一遍升级流程里面的内容,你可以直接跳过很多坑。
  3. 如果遇到具体的错误,可以去流水账里面找相应的问题和解决方法。

升级的坑我简单分几类:

  1. 一类是配置的问题,Taro的架构变了,依赖变了,配置结构也变了,导致有很多编译运行的问题. 这是最难搞的,因为这属于Taro私有设计,除了Taro官方的网站,很难在其它地方找到说明.
  2. 第二个是Taro的运行时变化。以前很多都是编译时绑定的代码。以前的react, mobx,Taro自己封装一遍,在编译器绑定,现在呢,都直接用原生的包了,不封装了, 运行时绑定。那么这个升级时要特别注意,小心.
  3. 第三类,Taro的生命周期变化。Taro 2的时候还有主动调用Taro.render(<App />, document.getElementById('app')), Taro 3里面没有了,是被动调用了。Taro 2的代码在Taro 3下就怎么也跑不起来了。这种坑不说,很难发现。
  4. 第四类,Taro有一些隐式绑定(运行时绑定),编译能过,跑的时候不能过,抛的错就定位不是非常清晰。
  5. 第五类是接口升级,因为很多库版本也跟着升级了,有一些库一些用法和接口也不一样,也会发现一些问题。 这些干扰因素会造成很多不必要的困扰,让你误判问题所在,兜圈子,浪费时间。
  6. Taro 版本共存的问题. 这个问题会在升级流程的最前面说一下解决办法。

下面我会简单记录一下升级的流程, 然后记一下出错处理流水账, 再尽可能的对Taro做一些分析, 解释一下为何会有那些问题。

升级流程

升级主要有以下几步流程,大家可以参考。

升级前请先新建一个taro 3的模板项目,下面要用到。

Taro版本共存

升级的时候可能需要不同版本的taro共存。 包括taro库和taro cli的共存。

taro库不用说了,在package.json里面。 重点是taro cli. 如果有全局的taro cli, 不同的taro项目编译就会有环境冲突。

解决办法是,

  1. 删除全局taro cli: yarn global remove @tarojs/cli, 在我另外一篇文章调试taro代码有提到.
  2. 创建项目的时候用npx命令: npx @tarojs/cli init xxxx
  3. taro cli不要全局安装, 写到package.json 的devDependency里面去. 这样项目会优先用当前目录下的taro工具版本.
     // for taro 3
       "devDependencies": {
         "@babel/core": "^7.8.0",
         "@tarojs/cli": "^3.0.26",
    

解决了taro 环境共存的问题,接下来就可以正式进入升级环节了。

0. 读升级文档

升级前先读从旧版本迁移到 Taro Next, 这片文章非常好! 好在哪地方?

第一,它是官方文档,可信。

第二,它用词非常讲究,给人一种力量!文章的精华就在第一段,它让人读完以后精神备受鼓舞,斗志昂扬,内心的冲动按耐不住,迫不及待得去动手升级。 这篇文章给人以精神的力量,给人以信心和勇气!我们踩坑缺的不就是这个么?

然后,你就在遇到问题->解决问题->新问题->解决问题->新问题…的跌宕起伏中,被希望和失望反复折磨!

相信我,能这样折磨你的,除了你的初恋,就只剩下升级Taro这件事了。

这篇教程可以做为优秀的励志技术类文章范文!

我只读类第一段,然后就开始了。 后面的两段遇到问题后回头看过,看不懂,等于没有看,怪自己。

对于学有余力的同学,可以再看看Taro 版本升级权威指南, 大佬(隔壁老李)写的,还是挺深入的。 这篇我也没有仔细看过, 主要是看不懂。

升级完后回头看,泪两行!

1. 升级package.json

这是第一步,非常重要,建议老老实实按照最后一句的做法去做!

从旧版本迁移到 Taro Next 这篇文章有告诉你怎么升级主要的packages。我告诉你,这是不够的。

  1. 因为Taro 3里面有新的preset,babel-preset-env不用了, babel-preset-taro, 需要添加到devDependencies里面去。 而Taro 2依赖的一些devDependencybabel-plugin-transform-runtime不需要单独配置了,还有一些devDependency被废弃,不移除会导致编译器不正常工作.
  2. @taro/mobx 已经不支持了,要换成mobxmobx-react
  3. regenerator-runtime 这个坑人,要去掉.

搞来搞去,你会陷入试错的汪洋大海之中,到最后,你也搞不清楚哪个包是对的,哪个是错的。

你会和我一样,绕来绕去,浪费大把的青春时光, 本应该把妹,晒太阳的,却被迫摸键盘,面对冰冷的机器,遭受无情的嘲笑,还搞不定。

最后怎么搞? 老老实实,新建一个Taro 3模板项目,把里面的package.json拷贝过来,覆盖,然后把自己的依赖一项一项添加。 相信我,这样做笨了点,但管用,能减少无意义的生命浪费。

##babel.config.js 从上面新建的模板项目里直接拷贝过来,什么也不用改。

2. 替换config/index.js

这个配置文件改动非常大,坑了我非常多时间。

从模板项目里面拷贝config/index.js覆盖,注意,是覆盖! 然后再想办法把自己需要的配置加回来。

到这里,大概率应该就可以运行yarn dev:weapp 进行编译了,是不是很Happy?

别高兴太早! 后面还有更坑人了,后面的坑编译器都不吱声, 静静等着你。

3. 所有的Taro.Component替换为React.Component

Taro不再自己封装React/Nerv/Vue等框架了,需要把所有import {Component} from "@tarojs/taro" 替换为 import {Component} from "react".

4. 修改src/app.jsx

这个地方我挺惊讶的,Taro启动方式变了,这么重要的事情, 官方升级文档好像没有说明。

针对app.jsx, 除了Component的替换外,还需要以下两处非常重要的改动:

  1. 删除文件最后一行Taro.render(<App />, document.getElementById('app'))
  2. 添加一行export default App

要不然,你就拼命挣扎吧!

5. import React

这是一个很神奇的bug, 在编译的时候代码不抛错,你也没有直接引用React, 但是,你得import React from "react", 要不然运行的时候会抛错, 找不到React。

你需要在每个页面顶部加下面一句, 保平安:

import React from "react"

6. mobx升级

如果你用到了mobx, 你得

  1. 把包@tarojs/mobx替换成mobx-react
  2. import { observer, inject } from '@tarojs/mobx' 替换成+import { observer, inject } from 'mobx-react'
  3. app.jsx: import { Provider } from '@tarojs/mobx' import { Provider } from 'mobx-react'
  4. app.jsx: <Provider store> 替换成 <Provider {...store} >. 这个根据你自己的实际情况调整.

6. 导出页面config

taro 3不认内嵌的config了,需要把config提到单独的文件里面去。

把页面里下面的内容:

// src/pages/settings/settings.jsx
    config = {
      navigationBarTitleText: '设置',
      enablePullDownRefresh: true,
      onReachBottomDistance: 50,
      usingComponents: {
      }
    }

抽到单独文件

// src/pages/settings/settings.config.js
    export default {
      navigationBarTitleText: '设置',
      enablePullDownRefresh: true,
      onReachBottomDistance: 50,
      usingComponents: {
        // "van-image": "../../components/vant-weapp/image/index"
      }
    }

做完上面的几步,大部分坑会消失。

问题流水账

接下来开始记流水账了。 把所有我遇到的报错记录下,然后提供对应的解决方法,仅供参考。同一个问题,不同的环境,原因也会不一样,解决方法也会有差异。

每个标题就是出错提示。下面有对应的解决方法。

Support for the experimental syntax ‘jsx’ isn’t currently enabled.

错误提示: Support for the experimental syntax 'jsx' isn't currently enabled.

这个是因为Taro preset的问题,babel配置的问题。

解决办法:

  1. 从模板项目里面拷贝babel.config.js到老项目里面去.
  2. 如果还有问题,注意按照安装步骤里面说的,把package.json覆盖一遍, 然后config/index.js覆盖一遍。
 // babel.config.js
 // babel-preset-taro 更多选项和默认值:
// https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md
module.exports = {
  presets: [
    ['taro', {
      framework: 'react',
      ts: false
    }]
  ]
}

缺少 app 全局配置,请检查!

错误提示: 缺少 app 全局配置,请检查!

原因: 3.0.2 版本需要把全局配置信息写到 app.config.ts 文件中,而不是直接写在app.jsx 文件中。

解决办法就是把app.jsx里面的config写入到app.config.js里面去, 直接export default 配置内容就可以了:

// app.config.js
export default {
  pages: [
    'pages/index/index'
  ],
  window: {
    backgroundTextStyle: 'light',
    navigationBarBackgroundColor: '#fff',
    navigationBarTitleText: 'WeChat',
    navigationBarTextStyle: 'black'
  }
}

Support for the experimental syntax ‘decorators-legacy’ isn’t currently enabled

错误提示: Support for the experimental syntax 'decorators-legacy' isn't currently enabled

package.json升级和config/index.js配置升级的问题,参考升级流程1、2。

Cannot read property ‘onShareAppMessage’ of undefined

出错提示: Cannot read property 'onShareAppMessage' of undefined

解决办法:

走一遍升级流程3、4.

Cannot read property ‘mount’ of undefined

出错提示: Cannot read property 'mount' of undefined

原因分析: Taro 2架构为编译型架构,也就是编译期就绑定React的引用了. Taro 3为运行时架构,编译器不绑定React, 运行时绑定。所以,你要在代码里面显示import React, 无论你页面是否有显示引用React. Taro 架构参考Taro 版本升级权威指南.

大家如果对Taro加载逻辑感兴趣,可以测试断点函数common.ts-> mount进行调试.

解决办法, 在页面的顶部加入下面一句:

import React from "react"

Error: MobX injector: Store ‘lessonStore’ is not available! Make sure it is provided by some Provider.

出错提示:

Error: MobX injector: Store 'lessonStore' is not available! Make sure it is provided by some Provider.

原因分析:

Mobx provider的绑定发生了变化,不自动展开store了。

解决办法:

app.jsx: <Provider store> 替换成 <Provider {...store} >.

ReferenceError: React is not defined

出错提示:

运行时抛ReferenceError: React is not defined错误.

解决办法, 在每个页面的顶部加入下面一句:

import React from "react"

react.ts:54 TypeError: Object(…) is not a function

出错提示:

在一个纯函数页面里,抛错react.ts:54 TypeError: Object(...) is not a function.

原因:

React很多类型定义是在运行时绑定。

解决办法:

  1. 在每个页面的顶部加入下面一句:
      import React from "react"
    
  2. import {useState, useEffect} from 'react' 替换为import {useState, useEffect} from '@tarojs/taro'

页面配置不起作用,标题不对

原因, config要独立到xxx.config.js里面去。

解决办法, 参考升级流程步骤6.

Error: module “pages/about/about.js” is not defined

这是一个Taro里面的常量,或者说是宏替换的问题,叫常量有误导性,容易踩坑, 我就是这么进坑的。

这个坑大部分人应该不会踩。我记录下来是想告诉大家一个调试的思路。

这个页面看上去一切正常,没有什么语法问题。 编译完也没问题。 运行的时候就是没法正常加载这个页面,提示有一个什么unexpected token :, 我把页面里面所有可疑的:都尝试改了一下,不能解决问题。

折腾了很久,无果。

后来, 查看了一下编译后的文件,发现了下面诡异的东西:

// 编译后的about.js
this.state={
    contact: 联系地址: xxxxxx
}

编译前是这样的:

// about.jsx
this.state = {
    contact: CONTACT_INFO
}

CONTACT_INFO 是一个常量(宏), 赋值为'联系地址: xxxxxx', 看上去很正常的一个字符串。

坑出来了,Taro替换的时候会把CONTACT_INFO的值的最外层引号去掉,然后再引用它的地方替换,于是就出现上面的运行时错误。

这个坑我踩了两次。

解决办法: 给CONTACT_INFO 再套一层双引号: '"联系地址: xxxxxx"'

我记录这个问题不是要喷这个常量替换有多容易踩坑(立个flag, 这个坑是新人必踩的), 我是想说,不要总盯着原文件改问题,大胆地看一看编译后的内容,可能会有惊喜。

最后

个人精力有限,细节难以非常详述,更欢迎大家在微信群里讨论。

祝Taro越来越好,国产的这么棒的东西,值得支持!

参考

没有太多参考,都是摸索出来的,taro的资料还是有点少。 享受一下自主踩坑的乐趣吧。

  1. Taro 版本升级权威指南
  2. 从旧版本迁移到 Taro Next
  3. Taro代码调试