解決移動端h5的動態polyfill問題

背景

目前咱們h5主要是面向兩個app,V(簡稱)以及W(簡稱)(都只是安卓端),基本都是基於這兩個app的webview作一些活動 W(簡稱) 面向最低的Android版本是4.1,V(簡稱) 面向最低的Android版本是4.0。低版本的手機js環境比較老,所以一些咱們要針對低版本的手機作一些polyfill補充(例如babel-polyfill,react-intl的polyfill => intl,vw/vh 等等)。php

咱們的polyfill主要是針對在4.2以及4.2如下的手機.css

這是 V(簡稱) 的手機型號用戶佔比: 4.2以及如下的手機uv大概100萬,佔比大概1.72%
html

image.png

這是 W(簡稱) 的手機型號用戶佔比: 4.2以及如下的活躍設備數量大概350萬,Dau大概120萬,4.2如下的設備大概1.5萬,佔比不到1%
react

image.png

目前的策略

目前咱們的方法是統一引入這些polyfill!
這是咱們某個活動頁面的build出來的結果,用BundleAnalyzerPlugin查看能夠看到,整個活動應用300多kb,而 code-js(babel-polyfill) + react-intl/lib  就已經佔了200多kb! 即便gzip以後傳輸也得66kb。
webpack

image.png

痛點

  1. 這些polyfill其實只是不多的一部分機型須要,而如今的狀況是全部的用戶都要承受加載它們的痛苦。
  2. 咱們活動的dau和pv很大(齋月活動等dau達到200-300萬),加載多餘的js也消耗咱們不少的流量費用。

解決方案

對於babel-polyfill

由於目前咱們的h5主要是面對於app的webview,app提供給咱們 jsBridge 讓咱們拿到手機的版本信息。
咱們沒有必要直接統一引入babel-polyfill,由於只有一小部分的用戶須要,吸取阿里巴巴的babel-polify動態接入方案,它們提供了對應的polyfill cdn.git

//polyfill.alicdn.com/polyfill.min.js?features=default,es2017,es6,fetch,RegeneratorRuntime
複製代碼

而咱們能夠在拿到手機的版本後,判斷低於4.2及如下的版本,才引入cdn作兼容處理。es6

對於react-intl(國際化)

與babel-polyfill相似,react-intl 須要給沒有內嵌intl的手機引入intl包,咱們能夠判斷window.Intl對象是否存在,不存在就動態下載這個包而且引入(要考慮阻塞渲染的狀況)。github

import * as React from 'react';
import request from "request";
import Spinner from "@/component/welike_spinner/welike_spinner"
import { IntlProvider } from "react-intl";
interface Props {
  messages: Object;
  children: React.ReactNode;
}
/**
 * 多語言組件,由於某些瀏覽器沒有內嵌intl,因此會報錯,
 * 這時候須要動態下載polyfill,避免了不須要intl的用戶的冗餘加載
 */
const INTL_CDN = '//cdn.polyfill.io/v2/polyfill.js?features=Intl.~locale.en'
export default React.memo<Props>(({ messages, children }) => {
  //是否原本就有intl
  const hasIntl = !!window.Intl;
  const [loading, setLoadingState] = React.useState(!hasIntl);
  //若是沒有,就去下載
  if (!hasIntl) {
    request.loadScript(INTL_CDN).then(() => {
      //下載完才真正的展示UI
      setLoadingState(false);
    }).catch(err => {
      console.log(err);
    })
  }
  return !loading ? <IntlProvider key={'en'} locale={'en'} messages={messages}>
    {children}
  </IntlProvider> : <div style={{ position: 'absolute', top: '0', left: '0', width: '100%', height: '100%' }}>
      <div style={{
        position: 'absolute',
        left: '50%',
        top: '50%',
        transform: 'translate(-50%, -50%)'
      }} >
        <Spinner />
      </div>
    </div>

})

複製代碼

能夠看到,改爲動態加載後,少了快40kb的資源!web

對於vw vh兼容性

image.png
能夠看到,針對安卓Browser,vw,vh只能向下支持到4.3.

  1. 爲了移動端瀏覽器能安全的使用vw單位實現多屏適配,從而讓css代碼運行在各類尺寸的手機屏幕上,而且和設計稿保持一致
  2. 技術方案爲:經過js動態判斷當前瀏覽器是否支持vw單位,若是不支持,把全部css樣式中vw轉爲rem,並設置html font-size爲當前瀏覽器寬度 的 1/100, 從而使1rem=1vw;
  3. write once run everywhere, 開發者無需考慮多屏適配問題和vw兼容問題
  4. 使用盡量簡單,代碼量儘量少,儘量不阻塞頁面基礎樣式和邏輯 使用vw-polyfill能夠解決這個問題。

不僅是vw,vh. 還有其餘的一些css屬性也要作兼容,這個得一步步地去測試以及優化了.npm

Last but not least

因爲隨着咱們項目愈來愈大愈來愈多,咱們須要引入的polyfill的場景以及條件都愈來愈多。
參考咱們的設備佔比數據,其實4.2如下的設備佔比比較小,因此咱們開發的時候須要取決成本和人力以及收益去判斷是否必要去作這些兼容性,若是有些項目不須要兼容,有些項目須要,咱們能夠在webpack的entry統一配置是否須要兼容的字段,不須要兼容的,咱們直接默認給一個相似提示更新的優雅降級操做便可。

參考文獻

  1. 動態Polyfill解決方案
  2. Polyfill 方案的過去、如今和將來
  3. react-intl-polyfill
  4. vw-polyfill
相關文章
相關標籤/搜索