Taro编译H5深入探索

500 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情

前言

上一篇文章分享了Taro3编译H5端会出现部分api缺少的问题,同时也讲述了我的解决方案,这里我们就这个问题进行深入的探究一下。

工具

源码探究

这里我不过多关注Taro在webpack编译时,runner中发生了什么,只关注有关api相关的细节实现。

首先,Taro3的所有端的api的入口都是基于@tarojs/taro。这这里抛出了Taro对象,所以才可以通过Taro来直接获取api进行使用。

const { container, SERVICE_IDENTIFIER } = require('@tarojs/runtime')
const taro = require('@tarojs/api').default

...

module.exports = taro
module.exports.default = module.exports

通过这里,我们可以发现,taro在这里只是做了个简单的导入导出操作,真正的taro是从@tarojs/api文件中导出的。接下来,我们就直接进入package/taro-api文件夹下,直接找到入口文件index.js查看代码,核心部分大致是这样的:

const Taro = {
  Behavior,
  getEnv,
  ENV_TYPE,
  Link,
  interceptors,
  Current,
  getCurrentInstance,
  options,
  nextTick,
  eventCenter,
  Events,
  useDidShow,
  useDidHide,
  usePullDownRefresh,
  useReachBottom,
  usePageScroll,
  useResize,
  useShareAppMessage,
  useTabItemTap,
  useTitleClick,
  useOptionMenuClick,
  usePullIntercept,
  useShareTimeline,
  useAddToFavorites,
  useReady,
  useRouter,
  getInitPxTransform
}

Taro.initPxTransform = getInitPxTransform(Taro)
Taro.preload = getPreload(Current)
Taro.pxTransform = getPxTransform(Taro)

export default Taro

通过这里我们基本就初步找到了Taro导出api的地方了,而且通过这段代码可以确认到为什么之前的问题。这部分api是字啊这里重新定义固定导出的,其余的api是根据不同的端做了兼容处理,然后挂载到Taro对象上的。所以我们碰到的Taro报错,部分api缺少的问题,就是出现在这里,h5端的那部分api没有成功挂载上去。

恰好,经过一番寻找,我在Taro的官方文档中找到了佐证:

在 H5 环境,@tarojs/taro 会从 @tarojs/api 取与平台无关的 API,从 @tarojs/taro-h5 中取遵循小程序规范实现的 API,最终集合成一个 Taro 对象暴露给开发者

经过一番搜索查找,我们最后锁定了taro-h5文件夹,进入入口文件index.ts之后,我们发现了下面这段代码

import Taro from './api/taro'

export * from './api/index'
export * from './api/taro'

export default Taro

这里导出了一个默认的Taro,是从api文件夹下的taro文件中引入的,另外将index和taro文件中导出的东西做了一次导入导出操作。

探索了一下taro.ts文件,发现跟taro-api文件的入口文件是很相似的,处理的是Taro对象,很可惜,不是我们要找的api。接下来,我们再来看index.ts文件

export * from './ad'
export * from './ai'
export * from './base'
export * from './canvas'
...
export * from './swan'

这个文件中只做了api下文件夹中所有的内容的导入导出,但是看了一下这些文件名,直觉告诉我们这就是我们要找的。我们进入其中一个base文件夹查看一下。

export const canIUse = temporarilyNotSupport('canIUse')

export function arrayBufferToBase64 (arrayBuffer) {
  return fromByteArray(arrayBuffer)
}

export function base64ToArrayBuffer (base64) {
  return toByteArray(base64)
}

这不就是我们通过Taro获取的api嘛,那就找到了,就是它。找到这里,我们也就理解了为什么会出现部分api缺少的问题了。也就反应过来了,问什么通过解构引入的方式可以解决了。

结语

好了,这里我们就只是简单的探索到这里了,更详细的研究我们后续再深入展开。欢迎大家在下方留言讨论。