Taro 是一个开放式跨端跨框架解决方案,支持使用 React/Vue/Nerv 等框架来开发 微信 / 京东 / 百度 / 支付宝 / 字节跳动 / QQ / 飞书 小程序 / H5 / RN 等应用。
现如今市面上端的形态多种多样,Web、React Native、微信小程序等各种端大行其道。当业务要求同时在不同的端都要求有所表现的时候,针对不同的端去编写多套代码的成本显然非常高,这时候只编写一套代码就能够适配到多端的能力就显得极为需要。
Taro 3 可以支持转换到 H5、ReactNative 以及任意小程序平台。
目前官方支持转换的平台如下:
Taro 3 只能配合使用 taro-ui@next 版本
安装命令:
npm i taro-ui@next
一款基于 Taro 框架开发的多端 UI 组件库。
Taro UI 特性:
Taro 开发 UI 组件ReactNative 端暂不支持)目前 Taro 仅提供一种开发方式:安装 Taro 命令行工具(Taro CLI)进行开发。
Taro CLI 依赖于 Node.js 环境,所以在你的机器上必须安装 Node.js 环境。安装 Node.js 环境有很多种方法,如果你完全不了解 Node.js 可以访问 Node.js 官网 下载一个可执行程序进行安装。我们推荐安装 LTS 版本的 Node.js(目前 LTS 版本是 v12)。
目前 Taro 仅提供一种开发方式:安装 Taro 命令行工具(Taro CLI)进行开发。
Taro CLI 依赖于 Node.js 环境,所以在你的机器上必须安装 Node.js 环境。安装 Node.js 环境有很多种方法,如果你完全不了解 Node.js 可以访问 Node.js 官网 下载一个可执行程序进行安装。我们推荐安装 LTS 版本的 Node.js(目前 LTS 版本是 v12)。
当你的机器已经存在了 Node.js 环境,可以通过在终端输入命令 npm i -g @tarojs/cli 安装 Taro CLI。安装完毕之后,在终端输入命令 taro,如果出现类似内容就说明安装成功了:
- 👽 Taro v3.0.0-beta.6
-
- Usage: taro <command> [options]
-
- Options:
- -V, --version output the version number
- -h, --help output usage information
-
- Commands:
- init [projectName] Init a project with default templete
- config <cmd> Taro config
- create Create page for project
- build Build a project with options
- update Update packages of taro
- convert Convert weapp to taro
- info Diagnostics Taro env info
- doctor Diagnose taro project
- help [cmd] display help for [cmd]
安装好 Taro CLI 之后可以通过 taro init 命令创建一个全新的项目,你可以根据你的项目需求填写各个选项,一个最小版本的 Taro 项目会包括以下文件
- ├── babel.config.js # Babel 配置
- ├── .eslintrc.js # ESLint 配置
- ├── config # 编译配置目录
- │ ├── dev.js # 开发模式配置
- │ ├── index.js # 默认配置
- │ └── prod.js # 生产模式配置
- ├── package.json # Node.js manifest
- ├── dist # 打包目录
- ├── project.config.json # 小程序项目配置
- ├── src # 源码目录
- │ ├── app.config.js # 全局配置
- │ ├── app.css # 全局 CSS
- │ ├── app.js # 入口组件
- │ ├── index.html # H5 入口 HTML
- │ └── pages # 页面组件
- │ └── index
- │ ├── index.config.js # 页面配置
- │ ├── index.css # 页面 CSS
- │ └── index.jsx # 页面组件,如果是 Vue 项目,此文件为 index.vue
我们以后将会讲解每一个文件的作用,但现在,我们先把注意力聚焦在 src 文件夹,也就是源码目录:
每一个 Taro 项目都有一个入口组件和一个入口配置,我们可以在入口组件中设置全局状态/全局生命周期,一个最小化的入口组件会是这样:
- import React, { Component } from 'react'
- import './app.css'
-
- class App extends Component {
- render () {
- // this.props.children 是将要会渲染的页面
- return this.props.children
- }
- }
-
- // 每一个入口组件都必须导出一个 React 组件
- export default App
每一个入口组件(例如 app.js)总是伴随一个全局配置文件(例如 app.config.js),我们可以在全局配置文件中设置页面组件的路径、全局窗口、路由等信息,一个最简单的全局配置如下:
src/app.config.js
- export default {
- pages: [
- 'pages/index/index'
- ]
- }
Taro官网安装及使用:https://nervjs.github.io/taro/docs/GETTING-STARTED.html
1、安装node
2、安装镜像
可以使用淘宝的镜像 https://npm.taobao.org/打开命令终端 npm install -g cnpm --registry=https://registry.npm.taobao.org
3、安装 Taro 开发工具 @tarojs/cli
npm install -g @tarojs/cli
4、使用命令创建模板项目
taro init myApp
5、进入项目
cd myApp
6、打开项目阅览(这里操作的是H5)
npm run dev:h5
使用 Taro 的 build 命令可以把 Taro 代码编译成不同端的代码,然后在对应的开发工具中查看效果。
Taro 编译分为 dev 和 build 模式:
NODE_ENV 为 production 可以开启压缩,方便预览,但编译速度会下降。编译命令
- # yarn
- $ yarn dev:weapp
- $ yarn build:weapp
-
- # npm script
- $ npm run dev:weapp
- $ npm run build:weapp
-
- # 仅限全局安装
- $ taro build --type weapp --watch
- $ taro build --type weapp
-
- # npx 用户也可以使用
- $ npx taro build --type weapp --watch
- $ npx taro build --type weapp
-
- # watch 同时开启压缩
- $ set NODE_ENV=production && taro build --type weapp --watch # Windows
- $ NODE_ENV=production taro build --type weapp --watch # Mac
小程序开发者工具
下载并打开微信开发者工具,然后选择项目根目录进行预览。
需要注意开发者工具的项目设置:
- ├── dist 编译结果目录
- |
- ├── config 项目编译配置目录
- | ├── index.js 默认配置
- | ├── dev.js 开发环境配置
- | └── prod.js 生产环境配置
- |
- ├── src 源码目录
- | ├── pages 页面文件目录
- | | └── index index 页面目录
- | | ├── index.js index 页面逻辑
- | | ├── index.css index 页面样式
- | | └── index.config.js index 页面配置
- | |
- | ├── app.js 项目入口文件
- | ├── app.css 项目总通用样式
- | └── app.config.js 项目入口配置
- |
- ├── project.config.json 微信小程序项目配置 project.config.json
- ├── project.tt.json 字节跳动小程序项目配置 project.tt.json
- ├── project.swan.json 百度小程序项目配置 project.swan.json
- ├── project.qq.json QQ 小程序项目配置 project.qq.json
- |
- ├── babel.config.js Babel 配置
- ├── tsconfig.json TypeScript 配置
- ├── .eslintrc ESLint 配置
- |
- └── package.json
编译配置存放于项目根目录下的 config 目录中,包含三个文件:
index.js 是通用配置dev.js 是项目预览时的配置prod.js 是项目打包时的配置详细的编译配置文档请查阅:编译配置详情
config/index.js
- const config = {
- // 项目名称
- projectName: 'Awesome Next',
- // 项目创建日期
- date: '2020-6-2',
- // 设计稿尺寸
- designWidth: 750,
- // 设计稿尺寸换算规则
- deviceRatio: {
- 640: 2.34 / 2,
- 750: 1,
- 828: 1.81 / 2
- },
- // 项目源码目录
- sourceRoot: 'src',
- // 项目产出目录
- outputRoot: 'dist',
- // Taro 插件配置
- plugins: [],
- // 全局变量设置
- defineConstants: {},
- // 文件 copy 配置
- copy: {
- patterns: [
- ],
- options: {
- }
- },
- // 框架,react,nerv,vue, vue3 等
- framework: 'react',
- // 小程序端专用配置
- mini: {
- postcss: {
- autoprefixer: {
- enable: true
- },
- // 小程序端样式引用本地资源内联配置
- url: {
- enable: true,
- config: {
- limit: 10240
- }
- },
- cssModules: {
- enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
- config: {
- namingPattern: 'module', // 转换模式,取值为 global/module
- generateScopedName: '[name]__[local]___[hash:base64:5]'
- }
- }
- },
- // 自定义 Webpack 配置
- webpackChain (chain, webpack) {}
- },
- // H5 端专用配置
- h5: {
- publicPath: '/',
- staticDirectory: 'static',
- postcss: {
- autoprefixer: {
- enable: true
- },
- cssModules: {
- enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
- config: {
- namingPattern: 'module', // 转换模式,取值为 global/module
- generateScopedName: '[name]__[local]___[hash:base64:5]'
- }
- }
- },
- // 自定义 Webpack 配置
- webpackChain (chain, webpack) {},
- devServer: {}
- }
- };
-
- module.exports = function(merge) {
- if (process.env.NODE_ENV === 'development') {
- return merge({}, config, require('./dev'));
- }
- return merge({}, config, require('./prod'));
- };
在 Taro 中尺寸单位建议使用 px、 百分比 %,Taro 默认会对所有单位进行转换。在 Taro 中书写尺寸按照 1:1 的关系来进行书写,即从设计稿上量的长度 100px,那么尺寸书写就是 100px,当转成微信小程序的时候,尺寸将默认转换为 100rpx,当转成 H5 时将默认转换为以 rem 为单位的值。
如果你希望部分 px 单位不被转换成 rpx 或者 rem ,最简单的做法就是在 px 单位中增加一个大写字母,例如 Px 或者 PX 这样,则会被转换插件忽略。
结合过往的开发经验,Taro 默认以 750px 作为换算尺寸标准,如果设计稿不是以 750px 为标准,则需要在项目配置 config/index.js 中进行设置,例如设计稿尺寸是 640px,则需要修改项目配置 config/index.js 中的 designWidth 配置为 640:
/config/index.js
- const config = {
- projectName: 'myProject',
- date: '2018-4-18',
- designWidth: 640,
- ....
- }
目前 Taro 支持 750、 640 、 828 三种尺寸设计稿,他们的换算规则如下:
- const DEVICE_RATIO = {
- '640': 2.34 / 2,
- '750': 1,
- '828': 1.81 / 2
- }
建议使用 Taro 时,设计稿以 iPhone 6 750px 作为设计尺寸标准。
如果你的设计稿是 375 ,不在以上三种之中,那么你需要把 designWidth 配置为 375,同时在 DEVICE_RATIO 中添加换算规则如下:
- const DEVICE_RATIO = {
- '640': 2.34 / 2,
- '750': 1,
- '828': 1.81 / 2,
- '375': 2 / 1
- }
INFO
Taro v3.4.3 开始支持配置函数形式的 designWidth,借此开发者可以动态地设置 designWidth,详情请查看:config.designWidth
https://taro-docs.jd.com/taro/docs/config-detail#designwidth
在编译时,Taro 会帮你对样式做尺寸转换操作,但是如果是在 JS 中书写了行内样式,那么编译时就无法做替换了,针对这种情况,Taro 提供了 API Taro.pxTransform 来做运行时的尺寸转换。
Taro.pxTransform(10) // 小程序:rpx,H5:rem
默认配置会对所有的 px 单位进行转换,有大写字母的 Px 或 PX 则会被忽略。
postcss.pxtransform 的参数默认值如下:
config/index.js
- config = {
- mini: {
- postcss: {
- pxtransform: {
- enable: true,
- config: {
- onePxTransform: true,
- unitPrecision: 5,
- propList: ['*'],
- selectorBlackList: [],
- replace: true,
- mediaQuery: false,
- minPixelValue: 0
- }
- }
- }
- }
- h5: {
- postcss: {
- pxtransform: {
- enable: true,
- config: {
- onePxTransform: true,
- unitPrecision: 5,
- propList: ['*'],
- selectorBlackList: [],
- replace: true,
- mediaQuery: false,
- minPixelValue: 0
- }
- }
- }
- }
- }
onePxTransform (Boolean)设置 1px 是否需要被转换
unitPrecision (Number)REM 单位允许的小数位。
propList (Array)允许转换的属性。
* to enable all properties. Example: ['*']* at the start or end of a word. (['*position*'] will match background-position-y)! to not match a property. Example: ['*', '!letter-spacing']['*', '!font*']selectorBlackList黑名单里的选择器将会被忽略。
['body'] will match .body-class[/^body$/] will match body but not .bodyreplace (Boolean)直接替换而不是追加一条进行覆盖。
mediaQuery (Boolean)允许媒体查询里的 px 单位转换
minPixelValue (Number)设置一个可被转换的最小 px 值
配置规则对应到 config/index.js ,例如:
/config/index.js
- {
- h5: {
- publicPath: '/',
- staticDirectory: 'static',
- postcss: {
- autoprefixer: {
- enable: true
- },
- pxtransform: {
- enable: true,
- config: {
- selectorBlackList: ['body']
- }
- }
- }
- },
- mini: {
- // ...
- postcss: {
- pxtransform: {
- enable: true,
- config: {
- selectorBlackList: ['body']
- }
- }
- }
- }
- }
当前忽略单个属性的最简单的方法,就是 px 单位使用大写字母。
- /* `px` is converted to `rem` */
- .convert {
- font-size: 16px; // converted to 1rem
- }
-
- /* `Px` or `PX` is ignored by `postcss-pxtorem` but still accepted by browsers */
- .ignore {
- border: 1Px solid; // ignored
- border-width: 2PX; // ignored
- }
对于头部包含注释 /*postcss-pxtransform disable*/ 的文件,插件不予处理。
样式文件里多行文本省略时我们一般如下面的代码:
- .textHide {
- display: -webkit-box;
- -webkit-box-orient: vertical;
- -webkit-line-clamp:2;
- text-overflow: ellipsis;
- overflow: hidden;
- }
但 Taro 编译后少了 -webkit-box-orient: vertical; 这条样式属性,此时我们需要忽略掉这条样式
忽略样式方法 1 加入 CSS 注释强制声明忽略下一行
- /* autoprefixer: ignore next */
- -webkit-box-orient: vertical;
忽略样式方法 2 加入 CSS 注释强制声明注释中间多行
- /* autoprefixer: off */
- -webkit-box-orient: vertical;
- /* autoprefixer: on */
忽略样式方法 3 写成行内样式
- <View
- style={{
- display: '-webkit-box',
- '-webkit-box-orient': 'vertical',
- '-webkit-line-clamp': 2,
- 'text-overflow': 'ellipsis',
- overflow: 'hidden',
- 'line-height': 2
- }}
- >
- 这是要省略的内容这是要省略的内容这是要省略的内容
- </View>
Taro 项目的 Babel 配置位于根目录的 babel.config.js 文件中,里面默认添加了一个 preset:babel-preset-taro,它会根据项目的技术栈添加一些常用的 presets 和 plugins。
babel.config.js
- module.exports = {
- presets: [
- ['taro', {/** 配置项 */}]
- ]
- }
开发者可以修改 babel.config.js,修改 babel-preset-taro 的配置项,或添加自己想要的 presets 和 plugins。
babel-preset-taro 会根据当前项目的技术栈,选择性地使用以下的 presets 和 plugins。
1. 通用
presets
@babel/preset-env@babel/preset-typescript(TypeScript 环境)plugins
@babel/plugin-transform-runtime@babel/plugin-proposal-decorators@babel/plugin-proposal-class-propertiesbabel-plugin-dynamic-import-node(小程序环境)2. React
presets
@babel/preset-reactplugins
react-refresh/babel3. Vue
presetes
@vue/babel-preset-jsx4. Vue3
plugins
@vue/babel-plugin-jsx以下将详细介绍 babel-preset-taro 的配置项。
NOTE
只在使用 React 时生效。
默认值:'automatic'
@babel/preset-react 的 runtime 配置项。
NOTE
只在使用 React 时生效。
默认值:true
是否引入 react-refresh/babel 来支持使用 fast-refresh。
NOTE
只在使用 Vue/Vue3 时生效。
默认值:true
类型:true | false | object
是否使用 @vue/babel-preset-jsx(Vue)或 @vue/babel-plugin-jsx(Vue3)来支持使用 jsx。
当传入一个 object 时,等同于设置为 true,且该 object 将会作为 @vue/babel-preset-jsx(Vue)或 @vue/babel-plugin-jsx(Vue3)的参数。
默认值:
- {
- ios: '9',
- android: '5'
- }
@babel/preset-env 的 targets 配置项。
默认值:false
有效值:'entry' | 'usage' | false
useBuiltIns: 'entry'
INFO
优点:全局彻底 polyfill,就算 node_modules 中的依赖存在不兼容的代码,也能成功运行。
缺点:可能会引入冗余代码、影响全局变量。
当传入 'entry' 时,会把 @babel/preset-env 的 useBuiltIns 选项设为 'entry'、corejs 选项设为 '3'。
开发者需要在入口文件 app.js 中引入 core-js:
src/app.js
import "core-js"
Babel 会根据 targets,引入对应的 core-js 依赖。例如上述代码会被编译为:
dist/app.js
- import "core-js/modules/es.string.pad-start";
- import "core-js/modules/es.string.pad-end";
- // ...
当然,因为这时 Taro 把
corejs设置为'3',所以可以使用core-js@3手动按需引入的能力,详情请见文档。
useBuiltIns: 'usage'
INFO
优点:按需引入、不会影响全局变量。
缺点:默认不会处理 node_modules 中的依赖,需要手动配置 babel-loader。
当传入 'usage' 时,会把 @babel/plugin-transform-runtime 的 corejs 选项设为 3。
注意:传入
'usage'时, Taro 没有使用@babel/preset-env的useBuiltIns: 'usage'而是使用了@babel/plugin-transform-runtime的corejs: 3。原因在于:一、两者同时设置时会产生冲突。二、后者相对于前者,不会影响全局变量。
useBuiltIns: false
当传入 false 时,会把 @babel/preset-env 的 useBuiltIns 选项设为 false,此时不会引入 core-js。
默认值:false
同时是 @babel/preset-env、@babel/plugin-proposal-class-properties 的 loose 配置项。
默认值:false
@babel/preset-env 的 debug 配置项。
默认值:false
@babel/preset-env 的 modules 配置项。
@babel/preset-env 的 spec 配置项。
@babel/preset-env 的 configPath 配置项。
@babel/preset-env 的 include 配置项。
@babel/preset-env 的 exclude 配置项。
@babel/preset-env 的 shippedProposals 配置项。
@babel/preset-env 的 forceAllTransforms 配置项。
@babel/plugin-proposal-decorators 的 decoratorsBeforeExport 配置项。
默认值:true
@babel/plugin-proposal-decorators 的 lagacy 配置项。
默认值:开发者根目录 node_modules 中的 @babel/plugin-transform-runtime 的路径。
类型:string
@babel/plugin-transform-runtime 的 absoluteRuntime 配置项。
默认值:开发者根目录 node_modules 中的 @babel/plugin-transform-runtime 的版本号。
类型:string
@babel/plugin-transform-runtime 的 version 配置项。
NOTE
可以去掉冗余代码,对于一些严格限制包体大小的场景(比如 PWA 等)有帮助,但这也会去掉页面和组件的懒加载,导致 app.js 过大。
注意:h5 平台默认关闭,其他平台默认开启,小程序默认是不支持动态加载的,可以通过dynamic-import 插件提供该能力。
类型:boolean