前言
因为团队里有10多个 Taro 2.x 项目,在逐步的迭代过程中发现,taro2 已经无法满足产品同学的需求,很多新功能新特性 taro2 已经不支持,秉承着绝不能在前端卡脖子的原则,我决定将 Taro 2.x 项目升级到 Taro 3.x,并输出一套统一方案,让大家可以快速实现升级。
首先先说明,Taro 3 大部分用法还是和旧版本一样的,所以大家不要过于担心,升级成本并不高哦~
现在我们来一步步完成升级。
更新依赖
推荐指定版本安装,因为保不齐新版本可能会有莫名其妙的bug,我们求稳不求新。taro 版本更新日志可参照 releases,假设我们要安装 3.6.2
版本。
更新 CLI
bash
# 更新 CLI
$ npm i -g @tarojs/cli@3.6.2
一般情况下全局安装就可以,但是如果你像我一样,很多 taro2 和 taro3的项目同时开发的话,就需要安装到项目本地了,这样就可以避免全局安装的冲突。
bash
# 安装到项目本地
$ npm i @tarojs/cli@3.6.2 --save-dev
# 然后把package.json里的 Taro build 改一下,例如:
"scripts": {
"build:weapp": "taro build --type weapp",
"dev:weapp": "npm run build:weapp -- --watch",
},
#改成
"scripts": {
"build:weapp": "npx @tarojs/cli@3.6.2 --type weapp",
"dev:weapp": "npm run build:weapp -- --watch",
},
# 使用 npx 命令用本地的taro cli 来执行构建。
更新 taro 依赖全家桶
json
// package.json
"@tarojs/plugin-framework-react": "3.6.2", // 使用 react 开发
"@tarojs/react": "3.6.2",
"@tarojs/plugin-platform-weapp": "3.6.2",
"@tarojs/plugin-platform-tt": "3.6.2", // 如果还需要其他平台自行添加
"@tarojs/runtime": "3.6.2",
"@tarojs/mini-runner": "3.6.2",
"@tarojs/components": "3.6.2",
"@tarojs/taro": "3.6.2",
"babel-preset-taro": "3.6.2",
更新 babel.config.js
js
// babel-preset-taro 更多选项和默认值:
// https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md
module.exports = {
presets: [
['taro', {
framework: 'react',
ts: true,
}],
],
};
如果你使用了 webpack5 还需要安装 @tarojs/webpack5-runner
webpack5 是在 config 里配置的,后面会说
如果你使用了 eslint 或 stylelint 相关包,也同时更新一下。
改完之后依旧存在旧版本的 taro相关 的包大概率用不到可以直接删掉了。剩下的大家根据构建时的提示自行添加和删除包就行了。
更新项目/页面配置
在旧版本 Taro 中,页面/项目的配置挂载在类组件的类属性或函数式的属性上,通过 AST 分析取出来,然后生成 JSON 文件。
在 Taro Next 中,会有一个新的文件:.config.js , 代表你页面/项目文件的文件名,config 文件必须和页面/项目文件在同一文件夹。在这个文件里你可以使用任意合法的 JavaScript 语法,只要最终把配置作为对象通过 export default 出去即可:
js
// app.js 项目文件
class App extends Component {
render () {
return ...
}
}
// app.config.js
export default {
pages: [
'pages/index/index'
],
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: 'WeChat',
navigationBarTextStyle: 'black'
}
}
// index.js 页面文件
function Index () {
return ...
}
// index.config.js 页面配置
const title = '首页'
export default {
navigationBarTitleText: title
}
一个完整的项目文件结构示例会像这样:
. ├── app.config.js // 入口文件项目配置 ├── app.js ├── app.scss ├── components │ └── result.js // 组件若不使用第三方组件则无需配置 └── pages └── index ├── index.config.js // index 的页面配置 └── index.js
入口组件更改
函数式组件入口:
js
import React, { useEffect } from 'react'
// Taro 额外添加的 hooks 要从 '@tarojs/taro' 中引入
import { useDidShow, useDidHide } from '@tarojs/taro'
// 假设我们要使用 Redux
import { Provider } from 'react-redux'
import configStore from './store'
// 全局样式
import './app.css'
const store = configStore()
function App(props) {
// 可以使用所有的 React Hooks
useEffect(() => {})
// 对应 onShow
useDidShow(() => {})
// 对应 onHide
useDidHide(() => {})
return (
// 在入口组件不会渲染任何内容,但我们可以在这里做类似于状态管理的事情
<Provider store={store}>
{/* props.children 是将要被渲染的页面 */}
{props.children}
</Provider>
)
}
export default App
请依照以上示例,把你的入口组件自行进行相应更改,当然也可以改成类组件形式,参考入口组件
页面组件更改
把组件配置抽离出来到 *.config.js 中
diff
// foo.jsx
export default class Index extends Component {
- config = {
- navigationBarTitleText: '首页'
- }
render() {
return null;
}
}
+// foo.config.js
+export default config = {
+ navigationBarTitleText: '首页'
+};
diff
// foo.jsx
const Home = () => {
return ();
};
-Home.config = {
- navigationBarTitleText: '首页',
-}
export default Home
+// foo.config.js
+export default config = {
+ navigationBarTitleText: '首页'
+};
更改逻辑很简单,所以我们可以用工具来自动实现,后面会介绍。
样式
在 Taro Next 中,没有 组件的外部样式和全局样式 的概念,组件的配置(config.js)是无效的,页面和入口文件引入的 CSS 都会变成全局 CSS ,没有了 externalClasses 和 addGlobalClass 这两个概念。
如果你需要带作用域的 CSS,可以自行修改为 CSS Modules。
React 第三方库
如果你需要引入 React 相关生态的库,直接通过 npm install 安装然后引入使用即可,Taro 不会再维护类似于 taro-redux 、taro-mobx 之类的库。
diff
- import { useSelector } from '@tarojs/redux'
+ import { useSelector } from 'react-redux'
可以自行使用编辑器的搜索功能,替换掉所有相关代码。
编译配置
修改你的 config/index.js 配置文件,加入这两项
js
framework: 'react',
compiler: 'webpack5', // 如果你需要使用5
详细配置参考 编译配置详情
路由
在 Taro 2.x 中,通过 this.$router 访问当前组件/页面路由的详情。
在 Taro 3.x 等价的 API 是 @tarojs/taro 包中的 getCurrentInstance().router。
diff
class Foo extends Component {
componentWillMount() {
- console.log(this.$router);
+ console.log(getCurrentInstance().router)
}
}
此部分可以使用工具自动完成。
API
在 Taro 2.x 中,所有面向应用开发者的 API 都在 @tarojs/taro 包中。
在 Taro 3.x 中,将 React 的 API 从 react 包中引入,其它的 API 仍然从 @tarojs/taro 引入。
diff
- import Taro, { Component, useEffect } from '@tarojs/taro';
+ import React, { Component, useEffect } from '@tarojs/taro';
+ import Taro from '@tarojs/taro';
此部分可以使用工具自动完成。
taro2-to-next
这是一款可以自动将 Taro 2.x 项目升级到 Taro 3.x 项目的工具,当你完成了上述步骤中的手动修改项之后,就可以使用该工具来做剩余的工作了,可以节省你 80% 的工作。
使用
bash
# 全局安装
npm i -g taro2-to-next
在当前项目目录下执行,传入你要转换的目录,一般是src
bash
taro2-to-next -p ./src
-p 参数支持相对路径(相对命令行工作目录)和绝对路径。
工具不会直接修改你的原代码,而是生成一个新的被修改后的目录,如你传入 src ,则会在同路径生成 src-modified 目录。
⚠️ 虽然但是,在运行前请还是先提交你的本地代码修改。
脚本包括
替换 API 导入
在 Taro 2.x 中,所有面向应用开发者的 API 都在 @tarojs/taro 包中。
在 Taro 3.x 中,将 React 的 API 从 react 包中引入,其它的 API 仍然从 @tarojs/taro 引入。
diff
- import Taro, { Component, useEffect } from '@tarojs/taro';
+ import React, { Component, useEffect } from '@tarojs/taro';
+ import Taro from '@tarojs/taro';
页面组件更改
把组件配置抽离出来到 *.config.js 中
diff
// foo.jsx
export default class Index extends Component {
- config = {
- navigationBarTitleText: '首页'
- }
render() {
return null;
}
}
+// foo.config.js
+export default config = {
+ navigationBarTitleText: '首页'
+};
diff
// foo.jsx
const Home = () => {
return ();
};
-Home.config = {
- navigationBarTitleText: '首页',
-}
export default Home
+// foo.config.js
+export default config = {
+ navigationBarTitleText: '首页'
+};
路由
在 Taro 2.x 中,通过 this.$router 访问当前组件/页面路由的详情。
在 Taro 3.x 等价的 API 是 @tarojs/taro 包中的 getCurrentInstance().router。
diff
class Foo extends Component {
componentWillMount() {
- console.log(this.$router);
+ console.log(getCurrentInstance().router)
}
}
总结
至此,完成以上步骤后你的项目应该升级成功并且可以正常打包了,如遇其他未尽事项可参考 Taro 官方迁移指南,一般在编辑器里修改替换就可以解决,如果有其他坑欢迎交流反馈。