1.0.0 • Published 8 months ago

taro2-to-next v1.0.0

Weekly downloads
-
License
MIT
Repository
github
Last release
8 months ago

前言

因为团队里有10多个 Taro 2.x 项目,在逐步的迭代过程中发现,taro2 已经无法满足产品同学的需求,很多新功能新特性 taro2 已经不支持,秉承着绝不能在前端卡脖子的原则,将 Taro 2.x 项目升级到 Taro 3.x,并输出一套统一方案,让大家可以快速实现升级很必要。

首先先说明,Taro 3 大部分用法还是和旧版本一样的,所以大家不要过于担心,升级成本并不高哦~

现在我们来一步步完成升级。

更新依赖

推荐指定版本安装,因为保不齐新版本可能会有莫名其妙的bug,我们求稳不求新。taro 版本更新日志可参照 releases,假设我们要安装 3.6.2 版本。

更新 CLI

# 更新 CLI
$ npm i -g @tarojs/cli@3.6.2

一般情况下全局安装就可以,但是如果你像我一样,很多 taro2 和 taro3的项目同时开发的话,就需要安装到项目本地了,这样就可以避免全局安装的冲突。

# 安装到项目本地
$ 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 依赖全家桶

// 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

// 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 出去即可:

// 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

入口组件更改

函数式组件入口:

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 中

// foo.jsx
export default class Index extends Component {
-   config = {
-       navigationBarTitleText: '首页'
-   }
    render() {
        return null;
    }
}

+// foo.config.js
+export default config = {
+   navigationBarTitleText: '首页'
+};
// 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 之类的库。

- import { useSelector }  from '@tarojs/redux'
+ import { useSelector }  from 'react-redux'

可以自行使用编辑器的搜索功能,替换掉所有相关代码。

编译配置

修改你的 config/index.js 配置文件,加入这两项

  framework: 'react',
  compiler: 'webpack5', // 如果你需要使用5

详细配置参考 编译配置详情

路由

在 Taro 2.x 中,通过 this.$router 访问当前组件/页面路由的详情。

在 Taro 3.x 等价的 API 是 @tarojs/taro 包中的 getCurrentInstance().router。

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 引入。

- 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% 的工作。

使用

# 全局安装
npm i -g taro2-to-next

在当前项目目录下执行,传入你要转换的目录,一般是src

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 引入。

- import Taro, { Component, useEffect } from '@tarojs/taro';
+ import React, { Component, useEffect } from '@tarojs/taro';
+ import Taro from '@tarojs/taro';

页面组件更改

把组件配置抽离出来到 *.config.js 中

// foo.jsx
export default class Index extends Component {
-   config = {
-       navigationBarTitleText: '首页'
-   }
    render() {
        return null;
    }
}

+// foo.config.js
+export default config = {
+   navigationBarTitleText: '首页'
+};
// 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。

class Foo extends Component {
    componentWillMount() {
-       console.log(this.$router);
+       console.log(getCurrentInstance().router)
    }
}

总结

至此,完成以上步骤后你的项目应该升级成功并且可以正常打包了,如遇其他未尽事项可参考 Taro 官方迁移指南,一般在编辑器里修改替换就可以解决,如果有其他坑欢迎交流反馈。

1.0.0

8 months ago