跳到主要内容
版本:4.x

H5

本篇将介绍 H5 开发的相关内容,包括兼容性、注意事项等。

兼容性

ES5

JS 版本

为了更高的编译效率和更小的产物体积,V4 开始默认的 browserslist 配置调整为:

{
"browserslist": ["defaults and fully supports es6-module", "maintained node versions"]
}

如不存在 browserslist 相关配置,则会使用 @babel/preset-envtarget 默认配置,如下:

targets = {
ios: '9',
android: '5',
}

将代码编译为 ES5

V4.0.8 开始使用脚手架创建项目时新增了是否编译为ES5的确认项,如选择,生成的项目会在生产模式打包时将全量代码编译为 ES5。需要注意的是:编译为 ES5 会影响编译效率和产物体积。

也可以通过如下配置将代码编译为 ES5:

  1. 修改 browserslist
package.json
{
"browserslist": {
"development": ["defaults and fully supports es6-module", "maintained node versions"],
"production": ["last 3 versions", "Android >= 4.1", "ios >= 8"]
}
}
  1. 设置 BROWSERSLIST_ENV 环境变量,以便在不同环境使用不同的 browserslist 配置
config/index.js
process.env.BROWSERSLIST_ENV = process.env.NODE_ENV
  1. 修改 babel-preset-taro 的配置。文档
babel.config.js
useBuiltIns: process.env.TARO_ENV === 'h5' ? 'usage' : false
  1. 修改编译范围
config/prod.js
// 编译器为 webpack 时
h5: {
compile: {
include: [
// 确保产物为 ES5,如可以确认包含 ES6 代码的 node_modules,则可修改正则采用白名单方式缩小编译范围,以提升编译速度
filename => /node_modules\/(?!(@babel|core-js|style-loader|css-loader|react|react-dom))/.test(filename)
]
}
}

// 编译器为 vite 时
h5: {
legacy: true,
}

小程序可根据自己需求决定是否需要配置和 H5 一样的 include。

V4.0.8 之前的版本由于默认 exclude 了 @tarojs/components,而 exclude 优先级高于 include,所以需要按下述方法配置:

config/prod.js
h5: {
webpackChain (chain) {
chain.merge({
module: {
rule: {
myloader: {
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {},
},
],
},
},
},
});
}
}

其他注意事项

  • Taro 内置的 babel-loader 配置请查看 H5WebpackModule
  • V4.0.8 开始 @tarojs/components 也会经过 Babel 编译。
  • 除了通过 h5.compile 来新增 include 和 exclude,您也可使用 WebpackChain 来修改 Taro 内置的 babel-loader 配置。
  • 如果还会遇到兼容性问题(如 Android 4.4),可考虑以下几点:
    • 使用兼容性组件库(暂时只支持 React),见:兼容性组件库
    • 如遇到 Promise undefined 等问题,可在 index.html 中手动引入一个 Promise 的 polyfill。

组件库

Input 组件不受控制

在 React 框架中使用 Input 组件时,如果传入 Input 组件值并未更新,开发者对输入值的约束会失效。这是由于虽然用户输入触发了相关事件,但由于开发者约束值导致组件 props 并未实际触发组件更新导致,此时需要手动刷新组件内容。

相关 Issue

React 兼容性组件库

备注

Taro 3.2.4 开始支持

Taro3 的 H5 端组件库基于 Web Components,使用了 Stencil 框架进行开发。

Stencil 兼容性情况

但移动端对 Web Components 的支持还有一些问题,主要问题如下:

  • 安卓 4.4 白屏
  • 多行文字截断失效
  • 部分安卓机(OPPO、VIVO 居多),样式 visibility 切换失败导致页面白屏

因此,对兼容性要求强烈对开发者,可以使用 React 兼容性组件库代替默认的 Web Components 组件库。它完全基于 React 开发,兼容性良好,但是目前只适配了若干常用的组件,开发者请谨慎选择使用

使用方法

  1. 安装兼容性组件库
$ yarn add @tarojs/components-react
  1. 设置编译配置 h5.useHtmlComponents
config/index.js
module.exports = {
h5: {
useHtmlComponents: true,
},
}
  1. 启动编译
$ taro build --type h5 --watch

贡献流程

由于人力问题,Taro 团队的迭代重心仍在 Web Components 组件库上。也欢迎各位开发者为 React 兼容性组件库添砖加瓦,具体工作是把以 Stencil 语法开发的组件改为 React 语法(Stencil 支持 JSX,因此改造工作量不大)。具体开发流程请看:@tarojs/component-react

lazy-load

Taro-H5 打包时会将页面和组件拆分成独立的文件按需加载,但这么做会导致没有用到的页面和组件依旧会被打包,有一些场景(比如 PWA 等需要严格限制包体大小时)会因此受到一些困扰。

所以我们通过 babel 插件提供了移除懒加载的方法:

babel.config.js
module.exports = {
presets: [
[
'taro',
{
framework: 'react',
hot: false,
'dynamic-import-node': true, // 如果使用时遇到问题,可尝试将 devServer 配置项中的 hot 设置为 false
},
],
],
}

dataset

Taro-H5 在 3.3.1+ 版本才支持 data-* 设置参数到节点上,如需使用请升级到对应版本。

浏览器 IntersectionObserver 兼容

在 Taro H5 中,我们使用了 IntersectionObserver 来实现了 Image 组件和 createIntersectionObserver 方法,考虑到该对象在各端特别是移动端适配度已经很高,在 v3.6.23 版本开始考量移除了它的 polyfill 依赖,如若项目有 IE11 及以下浏览器需求可以通过以下配置启用该兼容模式。

// config/prod.js
module.exports = {
env: {
NODE_ENV: '"production"',
SUPPORT_TARO_POLYFILL: '"enabled"', // 默认值为 disabled
},
// ...
}

钉钉内核浏览器兼容

钉钉内核的浏览器部分特性和其他浏览器有所不同,需要专门适配(譬如标题不能切换等等)。由于需要引入 dingtalk-jsapi 将导致包体变大,故而默认关闭,如果需要可通过如下配置启用适配模块。

// config/prod.js
module.exports = {
env: {
NODE_ENV: '"production"',
SUPPORT_TARO_POLYFILL: '"enabled"', // 3.+ 默认值为 enabled; 4.+ 默认值为 disabled
},
// ...
}
说明
enabled启用全部 Polyfill
ObjectObject Scope Polyfill
Object.assignObject.assign Polyfill
Object.definePropertyObject.defineProperty Polyfill
IntersectionObserverIntersectionObserver Polyfill
disabled禁用全部 Polyfill

路由

路由模式

H5 支持使用 hash 路由模式和浏览器 history 路由模式,默认使用 hash 模式。可以修改 h5.router.mode 进行配置。

路由基准路径 basename

H5 支持设置路由 basename,可以修改 h5.router.basename 进行配置。

自定义路由

H5 支持设置自定义的路由影射规则,可以修改 h5.router.customRoutes 进行配置。

路由守卫

Taro H5 的路由实现基于 history 库,因此支持使用 history 库提供的一系列能力,路由守卫就是其中之一。

当用户返回上一页时,我们可以借助 historyBlocking Transitions 能力监听返回事件,根据一些判断逻辑(例如弹窗挽留用户)决定是否执行路由返回操作。

history 文档上的例子(例子中的 window.confirm 可以替换为自定义弹窗)
import { history } from '@tarojs/router'

function Index() {
useEffect(() => {
// Block navigation and register a callback that
// fires when a navigation attempt is blocked.
let unblock = history.block((tx) => {
// Navigation was blocked! Let's show a confirmation dialog
// so the user can decide if they actually want to navigate
// away and discard changes they've made in the current page.
let url = tx.location.pathname
if (window.confirm(`Are you sure you want to go to ${url}?`)) {
// Unblock the navigation.
unblock()

// Retry the transition.
tx.retry()
}
})
return () => unblock()
}, [])

return <View />
}

React

使用 React 开发 H5 时需要注意的一些问题。

fast refresh

React 在 H5 Dev 编译模式时默认开启了 fast refresh 功能。

但是当使用了自定义环境变量时会出现以下报错:

或配置了 Webpack devServer 关闭热更新:hot: false 时,会出现以下报错:

危险

Uncaught ReferenceError: $RefreshSig$ is not defined

这都是因为在 dev 环境,Taro 默认做了两件事情:

  • 使用 fast-refresh 的 Babel plugin
  • 把 Webpack 配置的 devServer.hot 设置为 true,会加入 fast refresh 的 loader。

而且 fast refresh 的 Babel plugin 和 loader 必须同时启用或关闭。

因此当出现上述报错时,或不希望开启 fast refresh 时,可以通过同时配置 Babel 和 Webpack 进行关闭:

config/index.js
const config = {
// ...
h5: {
devServer: {
hot: false,
},
},
}
babel.config.js
module.exports = {
presets: [
[
'taro',
{
framework: 'react',
hot: false,
},
],
],
}

服务端渲染(SSR)

社区 @SyMind 大佬提供了编译 NextJS 应用的插件 tarojs-plugin-platform-nextjs,用于支持 Web 端支持 SSR 能力,可以根据项目需要自行选择。

事件

__taroNotSupport

版本 3.5.6 开始支持该事件

Web 版本中调用不支持的组件或 API 时会触发该事件,可供开发者作统一配置处理。

interface IEventResult {
// 组件或 API 名称
name: string
// 类型
type: 'component' | 'method'
// 状态分类
category: 'temporarily' | 'weixin_corp' | 'permanently'
// 组件实例
instance?
// API 调用参数
args?: unknown?[]
}

组件编译模式

与小程序和 RN 一样,H5 也可以将编译为原生组件

使用方法

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 h5 [--watch]

尺寸转换

组件编译模式同样支持与 Taro 一致的尺寸转换,需要注意的是虽然 css 样式完成了转化,但是部分在代码中的单位转换需要依赖 pxTransform 完成。

- Taro.pxTransform(10)
+ Taro.pxTransform.bind(this)(10)

组件模式下,Taro 将尺寸配置关联到组件实例上,在调用相关代码时需要关联相关配置,这一点与正常模式相区别。