天天看點

hippy-react 支援轉小程式

背景

Hippy-react 官方并沒有提供同構小程式的方案;

思考:我們技術棧hippy-react,其他業務也有同構小程式的需求,是否可以支援項目一鍵轉小程式,減少重複開發;

目标:同構

項目倉庫:https://git.code.oa.com/melodyren/wx_hippy

基礎架構選型

這裡調研了業界開源架構;最主要的差別是 DSL;大多數遵循React文法或VUE文法;

我們團隊是基于Hippy-React開發,文法是react;

關于vue文法相關架構uiapp, mpvue ,wepy不在我們考慮接入範圍内;

我們主要對比了二個React文法架構:alita和taro;

hippy-react 支援轉小程式

image

  1. Alita業内首個React Native轉微信小程式引擎;Hippy React 基本相容 React Native 文法;
  2. 元件标簽: alita對齊hippy react是rn标簽,taro是小程式标簽;
  3. 樣式規範: alita對齊hippy react是stylesheet,taro是sass,less;
  4. Alita 編譯+運作時處理,(是基于元件的 template,動态 “遞歸” 渲染整棵樹), 對JSX文法限制小;

    taro 2.0之前版本對JSX有諸多限制,比如暫不支援render()之外定義JSX;但2.0版本也改為了編譯+運作時;

    這裡之前有輸出一篇文章:http://km.oa.com/group/38202/articles/show/415870 有興趣可以查閱;

  5. 包大小:alita 非常純碎,隻做了轉小程式功能;alita包更小,更有優勢;
  6. alita分包,原生元件,第三方元件都支援;

通過對比,alita更契合我們業務,改動最小;對項目傾入性更小;

當然如果比github start數和穩定性,taro更有優勢;但基于taro改造工程量有點大哦;

!!!基于alita進行改造,适配hippy-react;那麼如何轉呢?

整體架構

hippy-react 支援轉小程式

image

  1. 整體要有hippy-react 開發體驗;
  2. 元件和API對齊hippy官方API;
  3. 支援項目接入,優化webpack建構流程;
  4. 完成基礎庫同構;(此處是業務側邏輯同構,每個業務側不同);
  5. 支援第三方元件接入,比如trtc-room 是騰訊雲官方提供的音視訊元件,支援分平台處理;
  6. 性能優化;

如何做到元件/API對齊呢?

Alita對Hippy元件支援情況

- [x] View

- [x] Text

- [x] Image

- [x] TextInput

- [x] ScrollView

- [ ] ListView

- [ ] Animation

- [ ] AnimationSet

- [ ] ViewPage

- [ ] Navigato

- [ ] RefreshWrappe

- [x] Modal

其中

View

,

Text

,

Image

,

TextInput

,

ScrollView

,

Modal

,Alita均有提供,屬性和方法稍加修改基本可以做到支援;

ViewPager

,

ListView

,

RefreshWrapper

,

Navigator

需要額外擴充@areslabs/wx-react-native 去支援;

Animation

,

AnimationSet

是Hippy提供的動畫方案。Hippy的動畫則是完全由前端傳入動畫參數,由終端控制每一幀的計算和排版更新,減少了js端與native端的通信次數,是以也大大減少動畫的卡頓。而RN動畫是前端驅動,狀态值由前端計算,并且通過jsbridge傳入終端實作動畫。API對前端入門友好,并且友善狀态管理。由于二端實作差異有點大,目前還未實作同構;

通過修改後對Hippy元件支援情況

- [x] View

- [x] Text

- [x] Image

- [x] TextInput

- [x] ScrollView

- [x] ListView

- [ ] Animation

- [ ] AnimationSet

- [x] ViewPage

- [x] Navigato

- [ ] RefreshWrapper(包裝在listview)

- [x] Modal

Alita對Hippy子產品支援情況

常用基本已支援;平台相關的元件,均沒有實作

- [x] AsyncStorage

- [ ] BackAndroid 微信小程式限制

- [ ] Clipboard

- [x] Dimensions

- [ ] NetworkModule

- [ ] NetInfo

- [x] PixelRatio

- [x] Platform

- [x] Stylesheet

- [x] Timers

修改後對Hippy子產品支援情況

- [x] AsyncStorage

- [ ] BackAndroid 微信小程式限制

- [ ] Clipboard

- [x] Dimensions

- [ ] NetworkModule

- [x] NetInfo

- [x] PixelRatio

- [x] Platform

- [x] Stylesheet

- [x] Timers

由于alita提供的元件和hippy-react内置元件并不完全對齊;我們将alita 開源項目拉取下來到我們倉庫位址進行維護,并對wx-react-native子產品進行修改,拉齊元件和api;完成同構;

(正常情況下:隻要hippy-react 元件和api 有對應的小程式元件和api,我們就可以完成重構);

左側是需要支援元件,右側是對應小程式元件;

hippy-react 支援轉小程式

image

這裡是如何做到hippy 元件 和 小程式元件對齊的呢?我大概畫了一下流程圖:

hippy-react 支援轉小程式

image

小程式的js檔案,無法直接在React層運作,需要提供一個上層Viewpager的代理,這個代理将代替小程式Viewpager元件在React層運作;

第一步:一般需要在對應包的package.json檔案的wxComponents 字段指定,建立聯系;

第二步:繼承自RNBaseComponent,提供上下兩層互動資料能力,diff算法拿到變更傳給小程式setData;事件回調點選事件觸發了小程式事件再傳給react運作環境;

Alita架構運作原理

官方文檔:https://areslabs.github.io/alita/

hippy-react 支援轉小程式

image

Alita 轉小程式整體流程:webpack打包到js檔案,js檔案經過alita-loader處理收集資訊info, 然後經過babel-loader 處理,最後通過webpack的alita-plugins(多個)生成小程式檔案(wxml/wxss等)

Alita 的整體架構借鑒了 ReactNative,其上層存在一個為小程式定制的 mini-react,底層是負責實際渲染的小程式原生代碼。而中間存在一個兩層互相聯系的 bridge。

hippy-react 支援轉小程式

image

mini-react 負責運作所有 React 代碼邏輯,包括遞歸的建構元件樹結構,建立元件執行個體,執行元件對應生命周期,context 計算等等。其最終将生成一份描述小程式視圖的資料。這份資料通過 bridge 子產品傳遞到底層小程式。底層小程式執行個體調用 setData 方法把資料刷給自身,完成渲染。

如何內建到項目工程呢?

項目目錄規範 - 接入友善,隻須在之前項目目錄新增打包配置檔案alita.config.js 和小程式入口檔案index.wx.js

hippy-react 支援轉小程式

image

alita.config.js 說明:

const path = require("path");

module.exports = {
  name: "HelloWorldExpo",//生成的微信小程式項目名
  appid: "wxc88f41e36c417bff",//調試小程式的appid,由微信申請而來
  entry: "./projects/HelloWorldExpo/index.js",//定義頁面的入口檔案
  output: "./output/wx-dist/HelloWorldExpo",//輸出目錄,小程式生成代碼輸出目錄
  include: [ //符合alita規範,直接轉化的元件,alita使用的是webpack打包的方式,會使用alita-loader去解析
    path.resolve("./projects/HelloWorldExpo/"), // 指定項目
    //path.resolve("./library/components/CountPane.js"), //可以引入項目外的通用組局
    // path.resolve("node_modules", "@areslabs", "hello-rn")//可以引入npm包
  ],
  resolve: {
    alias: { //别名
      // "@tencent/hippy-react": "@areslabs/wx-react-native"
    },
    // symlinks: false
  },
  miniprogramComponents: { // 第三方元件
    // "trtc-room": "/weixin/components/trtc-room/trtc-room"
  }
};           

複制

符合alita規範,直接轉化的元件,可在配置檔案include 添加路徑, alita使用的是webpack打包的方式,會使用alita-loader去解析;

如果是對小程式内置元件或者對小程式自定義元件的使用,都是隻會在小程式平台生效,是以需要平台判斷,和ReactNative一樣,一般有兩種方式: 檔案内判斷和建立平台檔案

  1. 檔案内判斷 if (Platoform.OS === 'wx') {

    return 小程式的view // <-- 直接使用小程式元件

    } else {

    return Hippy-React的View // <-- 使用Hippy-React元件

    }

  2. 建立平台檔案:(建議差異比較大的)

    建立平台檔案的方式,即建立單獨的小程式.wx字尾檔案,比如Map.wx.js

入口檔案

React 元件會被轉化為 wxml/wxss/js/json 4個檔案, 這裡有一個例外:入口檔案。入口檔案裡面定義了所有的頁面,由于小程式的頁面必須預先定義在 app.json 檔案,json檔案是靜态的,無法在運作時處理,是以我們必須在轉化的時候就識别出

所有的頁面

,是以對于入口檔案的檔案要求是足夠的靜态,為了減少錯誤,盡量不要在入口檔案處理其它邏輯,僅将入口檔案用來定義路由頁面。

詳情請看官方文檔: https://areslabs.github.io/alita/入口檔案.html

import React, { PureComponent } from "react";
import { Router, Route } from "@areslabs/router";
import Room from "./pages/Room";
// import Player from "./components/Room/Player";
export default class App extends PureComponent {
  render() {
    return (
      <Router
        wxNavigationOptions={{
          // navigationBarTitleText: "",
          navigationBarBackgroundColor: "#291B54"
          // navigationBarTextStyle: "black"
        }}
        navigationOptions={{
          title: "相親房間"
        }}
      >
        <Route key="Room" component={Room} />
        {/* <Route key="Player" component={Player} /> */}
      </Router>
    );
  }
}           

複制

項目運作:

類似wepack執行,接入了yargs,支援三種模式,最終都是用alita-core去打包;

# 開發模式 
dating run-wx —dev [projectname]
# 打包模式 
dating run-wx --build [projectname] 
# 分析包模式
dating run-wx —analyzer [projectname]           

複制

const argv = yargs
    .command(COMMAND.RUN_WX, "運作 wx 環境", function(yargs) {
      var _argv = yargs
        .reset()
        .option("dev", {
          alias: "dev",
          demand: false,
          describe: "是否開發環境",
          type: "boolean"
        })
        .option("build", {
          alias: "build",
          demand: false,
          describe: "是否編譯環境",
          type: "boolean"
        })
        .option("analyzer", {
          alias: "analyzer",
          demand: false,
          describe: "分析包",
          type: "boolean"
        }).argv;
      if (_argv._ && _argv._[1]) {
        _argv.entry = _argv.e = _argv._[1];
      }
      process.argv.push("--config");
      process.argv.push("./projects/" + _argv.entry + "/alita.config.js");
      require("@tencent/alita-core/lib/index");
    })           

複制

微信小程式的體積是有限制的,“代碼體積小于 2M,分包 8M”。借助webpack的BundleAnalyzerPlugin插件,隻需要在執行時候添加 --analyzer 參數即可;

hippy-react 支援轉小程式

image

總結:Alita是基于RN轉小程式,hippy-react和RN 的差異主要是在元件和api,站在巨人的肩膀上,我們很容易實作hippy-react轉小程式;內建到工程需要看一下源碼,做相對應改造;

目前K歌輕緣相親做了簡單嘗試,歡迎大家體驗(完整流程是下載下傳相親APP,打開相親房間,分享相親房間到微信,可以在微信内觀看直播相親哦)

hippy-react 支援轉小程式

image