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

H5

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

兼容性​

ES5​

JS 版本​

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

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

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

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 库提供的一系列能力,路由守卫就是其中之一。

当用户返回上一页时,我们可以借助 history 的 Blocking 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 将尺寸配置关联到组件实例上,在调用相关代码时需要关联相关配置,这一点与正常模式相区别。