解决 Vue3 在低版本 Android Webview 的兼容问题

2,720 阅读2分钟

问题

用 Vue3 实现了一个 h5 页面,运行在低版本 Android 的 WebView,会出现无法解析高级语法的问题,导致页面无法正常显示,或者功能异常的现象。

原因

项目是使用 Vite 搭建的,但是缺少了 babel 配置,虽然 Vite 正常来说不用配置 babel:

  • Vite 默认使用 esbuild 进行依赖预构建和 TypeScript/JSX 的转换

  • esbuild 比 Babel 快 10-100 倍,性能更优

  • 在开发环境中,Vite 利用浏览器原生 ESM 能力,无需像 Babel 那样进行完整的代码转换

  • 在生产构建时,Vite 使用 Rollup 进行打包

  • 除非你有特殊的转换需求,否则使用 Vite 时完全不需要手动配置 Babel。Vite 的现代构建方案已经很好地解决了代码转换和兼容性问题。

但在低版本Android的 webview 中,会出现 Vue3 项目不兼容的问题,造成这个问题的原因可能有:

  • 低版本 Android 系统的 WebView 不支持某些现代 JavaScript 特性

  • Vue3 使用了 Proxy 等现代特性,在低版本设备上需要降级处理

  • 缺少必要的 polyfills 支持

解决

  1. 方案一:在项目入口添加 polyfills,对 JS 高级语法做降级处理(对所有环境生效)
/**
 * 确保在应用程序代码之前引入 polyfill
 * 兼容低版本安卓
 */
import 'core-js/stable';
import 'regenerator-runtime/runtime';

import { createApp } from 'vue';
import App from './App.vue';
import router from '@/router';
// import '@/mocks';
import '@/assets/css/reset.scss';
import '@/assets/css/font.scss';
import '@/assets/css/global.scss';
import 'vant/lib/index.css';
import '@/assets/css/vant.scss';
import { createPinia } from 'pinia';
import VConsole from 'vconsole';

(function () {
  window.web_hidePage = function () {}
  window.web_showPage = function () {}

  if (import.meta.env.VITE_VUE_APP_ERUDA_OPEN !== '1') {
    return;
  }

  new VConsole();
})();


const app = createApp(App);
const pinia = createPinia();

app.use(router);
app.use(pinia);

app.mount('#app');

// micro-app 微前端,卸载应用,子应用卸载时会自动执行window.unmount
window.unmount = () => {
  app.unmount();
};

同时需要安装相关的依赖

  "dependencies": {
    "core-js": "^3.39.0",
    "regenerator-runtime": "^0.14.1"
  },
  1. 方案二:配置 vite.config.ts 的 legacy
import { defineConfig, loadEnv } from 'vite';
import legacy from '@vitejs/plugin-legacy';

export default ({ mode }: { mode: string }) => {
  const env = loadEnv(mode, process.cwd());

  return defineConfig({
    plugins: [
      legacy({
        targets: ['defaults', 'not IE 11', 'Chrome >= 53', 'Android >= 6'],
        additionalLegacyPolyfills: ['core-js/stable', 'regenerator-runtime/runtime'],
      }),
    ],
  });
};

同时需要安装相关的依赖

  "dependencies": {
    "core-js": "^3.39.0",
    "regenerator-runtime": "^0.14.1"
  },

其他问题

在测试过程中,发现不同手机厂商在相同的 Android 版本中的表现也有差异,比如有些手机支持某些高级 JS 语法,有些手机却不支持,所以最终经过测试了好几台主流厂商的Android6及以上的安卓机之后,发现上面写的 polyfills 降级处理是最全面的,应该能兼容很大一部分的Android6以上的机型。