原生项目使用 Taro
3.0.25
后开始支持在原生项目中部分使用 Taro 进行开发。
示例项目:
基础混合用法
App 入口
1. 以混合模式进行打包
编译项目时使用 --blended
参数以输出混合模式的代码。
taro build --type weapp --blended
taro build --type weapp --watch --blended
2. 移动 Taro 项目的输出目录到原生项目内
可以编写一个 Taro 插件自动移动,可以参考 plugin-mv。
3. 原生项目的 app.js 中引用 Taro 入口文件
app.config.js
// 必须引用 Taro 项目的入口文件
const taroApp = require('./taro/app.js').taroApp
App({
onShow () {
// 可选,调用 Taro 项目 app 的 onShow 生命周期
taroApp.onShow()
},
onHide () {
// 可选,调用 Taro 项目 app 的 onHide 生命周期
taroApp.onHide()
}
})
引用原生项目的 JS 文件
有时我们需要在 Taro 项目中引用原生项目中的公共 js 模块,如上报 sdk。但是 Webpack 会把这些公共模块一并打包,导致公共模块存在两份(Taro 产物中一份,原生项目中一份)。
为了优化包体积大小,我们希望不要打包到 Taro 产物中,而是直接引用原生项目中的代码,可以使用 Webpack 的 externals 配置去实现。
例子
假设以下项目结构:
├── miniapp 原生项目
| └── utils
| └── util.js
└── taro-project Taro 项目
└── src
└── pages
└── index 此页面中希望引用 miniapp/utils/util.js
- 配置
alias
,目的是让externals
更方便地筛选出不需要打包的依赖。 - 配置 Webpack
externals
,选择出不需要打包的依赖,并计算好相对路径。 - 设置环境变量
process.env.NODE_ENV
为production
时,externals 生效。(当没有手动设置环境变量时,默认在watch
模式时环境变量为development
,否则为production
)
config/index.js
const config = {
alias: {
// 开发环境直接引用原生项目下的依赖,方便开发
'@/utils': process.env.NODE_ENV === 'production' ? path.resolve(__dirname, '../utils') : path.resolve(__dirname, '../../miniapp/utils')
},
mini: {
webpackChain (chain) {
chain.merge({
externals: [
(context, request, callback) => {
const externalDirs = ['@/utils']
const externalDir = externalDirs.find(dir => request.startsWith(dir))
if (process.env.NODE_ENV === 'production' && externalDir) {
const externalDirPath = config.alias[externalDir]
const res = request.replace('@/utils', path.relative(context, externalDirPath))
return callback(null, `commonjs ${res}`)
}
callback()
},
]
})
}
}
}
taro-project/src/pages/index/index.js
import { logSomething } from '@/utils/util'
logSomething()
webpack 打包结果
{
"./src/pages/index/index.jsx": (function(m, e, __webpack_require__) {
var _utils_util = __webpack_require__("@/utils/util");
// ...
}),
"@/utils/util": (function(module, exports) {
module.exports = require("../../../utils/util");
})
}
引用原生项目的原生组件
有时我们需要在 Taro 项目中引用原生项目中的公共自定义组件。
和引用原生项目的 js 文件一样,我们希望在开发环境能正确解析组件路径,在生产环境则直接引用原生项目的组件而不是重复打包,可以使用 Taro 的 alias 配置去实现。
例子
假设以下项目结构:
├── miniapp 原生项目
| └── components
| └── title
| ├── index.js
| ├── index.wxml
| ├── index.wxss
| └── index.json
└── taro-project Taro 项目
└── src
├── components 把原生项目的组件拷贝过来,让开发环境能正确解析组件
| └── title
└── pages
└── index 此页面中希望引用 miniapp/components/title
- 把原生项目的组件拷贝到 Taro 项目,让开发环境能正确解析组件。
- 根据开发环境和生产环境,正确配置
alias
config/index.js
const config = {
alias: {
'@/components': process.env.NODE_ENV === 'production' ? path.resolve(__dirname, '../components') : path.resolve(__dirname, '../../miniapp/components')
}
}
taro-project/src/pages/index/index.config.js
export default {
usingComponents: {
title: '@/components/title/index'
}
}
对 Taro 项目的部分页面分包
对 Taro 项目中部分页面进行分包。
依赖细分
Taro 默认会把页面共用的普通依赖打包到 common.js
,node_modules 依赖打包到 vendor.js
。
但是在分包时,我们会希望把只有在分包中共用的依赖打包到分包中,而不是打在主包的 common.js
和 vendor.js
中。这就需要我们对依赖进行细分,可以借助 Webpack 的 splitChunk 和 Taro 的 addChunkPages 配置去实现。
例子
假设以下项目结构:
├── dist
| |── common.js 公共依赖
| |── vendors.js node_modules 依赖
| └── subPackages
| ├── foo
| ├── bar
| └── common.js 只有 subPackages 子包中使用的公共依赖
└── src
└── subPackages
├── foo
└── bar
- 使用 Webpack splitChunks 把只有
subpackages
子包独有的依赖打包到subpackages/common.js
中。 - 使用 Taro addChunkPages 配置,在子包中所有页面的头部添加对
subpackages/common.js
的引用。
config/index.js
const config = {
mini: {
addChunkPages (pages) {
pages.set('subpackages/bar/index', ['subpackages/common']),
pages.set('subpackages/foo/index', ['subpackages/common'])
},
webpackChain (chain) {
chain.merge({
optimization: {
splitChunks: {
cacheGroups: {
subpackagesCommon: {
name: 'subpackages/common',
minChunks: 2,
test: (module, chunks) => {
const isNoOnlySubpackRequired = chunks.find(chunk => !(/\bsubpackages\b/.test(chunk.name)))
return !isNoOnlySubpackRequired
},
priority: 200
}
}
}
}
})
}
}
}
把 Taro 项目作为一个完整分包
使用方法
1. 安装使用插件
安装插件 @tarojs/plugin-indie
npm i @tarojs/plugin-indie --save-dev
使用插件
config/index.js
const config = {
plugins: [
'@tarojs/plugin-indie'
]
}
2. 以混合模式进行打包
编译项目时使用 --blended
参数以输出混合模式的代码。
taro build --type weapp --blended
taro build --type weapp --watch --blended
3. 移动 Taro 项目的输出目录到原生项目内
可以编写一个 Taro 插件自动移动,可以参考 plugin-mv。
4. 设置原生项目的分包配置
把 Taro 项目拆分到多个分包
假设有一个 Taro 项目,它含有页面 A 和页面 B。我们需要把页面 A 加入原生项目的其中一个分包 M,把页面 B 加入到另一个分包 N。
为此,和普通打出一个分包不同的是,首先需要配置 Webpack 的 output.jsonpFunction
配置,避免 chunkid
的冲突。
config/index.js
config = {
// ...
mini: {
webpackChain (chain) {
chain.merge({
output: {
// 可以配合 npm script 和环境变量来动态修改
jsonpFunction: process.env.JSONP_NAME || "webpackJsonp"
}
})
}
}
}
然后分别对 A、B 页面使用混合模式打包,步骤和把 Taro 项目作为一个完整分包一致。
把 Taro 组件编译为原生自定义组件
v3.1.2+,暂时只支持 React
Taro 支持把组件编译为原生小程序自定义组件,供原生项目使用。
使用方法
1. 配置组件路径
修改 app.config.js
,增加 components
配置,指向组件入口文件的路径:
app.config.js
export default {
// ...
components: [
'pages/index/index',
'components/picker/index'
]
}
2. 开始编译
使用 taro build native-components
命令,配合参数 type
,即可编译出对应平台的自定义组件。
taro build native-components --type [platform] [--watch]
props 传递
传递 props 给 Taro 编译出来的原生自定义组件时,需要统一通过 props
参数来传递:
page/index/index.js
Page({
data: {
pickerProps: {
mode: 'format',
value: [0, 0, 0],
onInitial (value, index) {
console.log('onInitial')
}
}
}
})
page/index/index.wxml
<!--index.wxml-->
<view>
<picker props="{{pickerProps}}"></picker>
</view>
Taro 组件 - Picker
function Picker ({ mode, value, onInitial }) {
return (
// ...
)
}