Back to Hippy

环境搭建

docs/development/native-integration.md

3.4.024.4 KB
Original Source

环境搭建

这篇教程,讲述了如何将 Hippy 集成到 Android、iOS、Ohos、Flutter、Web(同构) 等平台。

Android

注:以下文档都是假设您已经具备一定的 Android 开发经验。


前期准备

  • 已经安装了 JDK version>=1.7 并配置了环境变量
  • 已经安装 Android Studio 最新版本
  • 运行 Demo 工程前需要完成 NDK,CMAKE,gradle 与相关插件的安装

Demo 体验

若想快速体验,可以直接基于我们的 Android Demo 来开发

快速接入

  1. 创建一个 Android 工程

  2. Maven 集成

    • 查询 Maven Central Hippy 版本,其中 hippy-releaserelease 版本(不携带 inspector),hippy-debugdebug 版本

    • 配置 build.gradle

      下面引用Hippy最新版本号可在上述链接中查询

    java
     // implementation 'com.tencent.hippy:hippy-debug:3.0.1'
     implementation 'com.tencent.hippy:hippy-release:3.0.1'
     implementation 'androidx.legacy:legacy-support-v4:1.0.0'
     implementation 'androidx.recyclerview:recyclerview:1.1.0'
     implementation 'androidx.viewpager:viewpager:1.0.0'
    
  3. 本地集成(可选)

    • hippy-framework 工程运行 Gradle Task other => assembleRelease 或者 other => assembleDebug 后会在 framework/android/build/outputs/aar 目录下生成 release 或者 debug 模式的android-sdk.aar,将 android-sdk.aar 拷贝到你项目的 libs 目录下。

      !> 通过 assembleRelease task 生成的 AAR 默认不携带 inspector 模块,不能在前端通过 Devtools 对代码进行调试,若需要集成 inspector,请执行 assembleDebug task

    • 配置 build.gradle

    java
     api (name:'android-sdk', ext:'aar')
     implementation 'androidx.legacy:legacy-support-v4:1.0.0'
     implementation 'androidx.recyclerview:recyclerview:1.1.0'
     implementation 'androidx.viewpager:viewpager:1.0.0'
    
  4. 在宿主 APP 工程中增加引擎初始化与 hippyRootView 挂载逻辑,具体可以参考 Demo 工程中 HippyEngineWrapper 实现

iOS

注:以下文档都是假设您已经具备一定的 iOS 开发经验。

这篇教程,讲述了如何将 Hippy 集成到一个现有的 iOS 工程。


一、环境准备

  • 安装 Xcode

  • 安装 CMake

    推荐使用Homebrew安装CMake,安装命令如下:

    shell
    brew install cmake
    
  • 安装 CocoaPods

    CocoaPods 是一个iOS和macOS开发中流行的包管理工具。我们将使用它把Hippy的iOS Framework添加到现有iOS项目中。

    推荐使用Homebrew安装CocoaPods,安装命令如下:

    shell
    brew install cocoapods
    

若想快速体验,可以直接基于Hippy仓库中的 iOS Demo 来开发

二、使用 Cocoapods 集成 iOS SDK

具体的操作步骤如下:

  1. 首先,确定要集成的Hippy iOS SDK版本,如3.2.0,将其记录下来,接下来将在Podfile中用到。

    可到「版本查询地址」查询最新的版本信息

  2. 其次,准备好现有iOS工程的 Podfile 文件

    Podfile 文件是CocoaPods包管理工具的配置文件,如果当前工程还没有该文件,最简单的创建方式是通过CocoaPods init命令,在iOS工程文件目录下执行如下命令:

    shell
    pod init
    

    生成的Podfile将包含一些demo设置,您可以根据集成的目的对其进行调整。

    为了将Hippy SDK集成到工程,我们需要修改Podfile,将 hippy 添加到其中,并指定集成的版本。修改后的Podfile应该看起来像这样:

    text
    #use_frameworks!
    platform :ios, '11.0'
    
    # TargetName大概率是您的项目名称
    target TargetName do
    
        # 在此指定步骤1中记录的hippy版本号,可访问 https://github.com/Tencent/Hippy/releases 查询更多版本信息
        pod 'hippy', '3.2.0'
    
    end
    

    默认配置下,Hippy SDK使用布局引擎是Taitank,JS引擎是系统的JavaScriptCore,如需切换使用其他引擎,请参照下文《引擎切换(可选)》一节调整配置。

    !> 请注意,由于hippy3.x中大量使用了 #include"path/to/file.h" 的方式引用C++头文件,因此如果开启了 CocoaPods 的 framework 格式集成选项(即Podfile中 use_frameworks! 配置为开启状态),则必须在 Podfile 文件中加入如下配置:

    text
    # 工程开启 use_frameworks! 后需添加此环境变量,用于hippy使用正确设置项
    ENV["use_frameworks"] = "true"
    
  3. 最后,在命令行中执行

    shell
    pod install
    

    命令成功执行后,使用 CocoaPods 生成的 .xcworkspace 后缀名的工程文件来打开工程。

三、编写SDK接入代码,加载本地或远程的Hippy资源包

Hippy SDK的代码接入简单来说只需两步:

1、初始化一个HippyBridge实例,HippyBridge是Hippy最重要的概念,它是终端渲染侧与前端驱动侧进行通信的桥梁,同时也承载了Hippy应用的主要上下文信息。

2、通过HippyBridge实例初始化一个HippyRootView实例,HippyRootView是Hippy应用另一个重要概念,Hippy应用将由它显示出来,因此可以说创建业务也就是创建一个 HippyRootView

目前,Hippy 提供了分包加载接口以及不分包加载接口,使用方式分别如下:

方式1. 使用分包加载接口

objectivec
/** 此方法适用于以下场景:
 * 在业务还未启动时先准备好JS环境,并加载包1,当业务启动时加载包2,减少包加载时间
 * 我们建议包1作为基础包,与业务无关,只包含一些通用基础组件,所有业务通用
 * 包2作为业务代码加载
*/

// 先加载包1,创建出一个HippyBridge实例
// 假设commonBundlePath为包1的路径
// Tips:详细参数说明请查阅头文件: HippyBridge.h
NSURL *commonBundlePath = getCommonBundlePath();
HippyBridge *bridge = [[HippyBridge alloc] initWithDelegate:self
                                                  bundleURL:commonBundlePath
                                             moduleProvider:nil
                                              launchOptions:your_launchOptions
                                                executorKey:nil];

// 再通过上述bridge以及包2地址创建HippyRootView实例
// 假设businessBundlePath为包2的路径
// Tips:详细参数说明请查阅头文件: HippyRootView.h
HippyRootView *rootView = [[HippyRootView alloc] initWithBridge:bridge
                                                    businessURL:businessBundlePath
                                                     moduleName:@"Your_Hippy_App_Name"
                                              initialProperties:@{}
                                                   shareOptions:nil
                                                       delegate:nil];

// 最后,给生成的rootView设置好frame,并将其挂载到指定的VC上。
rootView.frame = self.view.bounds;
rootView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self.view addSubview:rootView];

// 至此,您已经完成一个Hippy应用的初始化,SDK内部将自动加载资源并开始运行Hippy应用。

方式2. 使用不分包加载接口

objectivec
// 与上述使用分包加载接口类似,首先需要创建一个HippyBridge实例,
// 区别是在创建HippyRootView实例时,无需再传入业务包,即businessBundlePath,直接使用如下接口创建即可
// Tips:详细参数说明请查阅头文件: HippyRootView.h
- (instancetype)initWithBridge:(HippyBridge *)bridge
                    moduleName:(NSString *)moduleName
             initialProperties:(nullable NSDictionary *)initialProperties
                  shareOptions:(nullable NSDictionary *)shareOptions
                      delegate:(nullable id<HippyRootViewDelegate>)delegate;

在Hippy仓库中提供了一个简易示例项目,包含上述全部接入代码,以及更多注意事项。

建议参考该示例完成SDK到已有项目的集成:iOS Demo,更多设置项及使用方式请查阅上述头文件中的具体API说明。

!> 使用分包加载可以结合一系列策略,比如提前预加载bridge, 全局单bridge等来优化页面打开速度。

到这里,您已经完成了接入一个默认配置下的Hippy iOS SDK的全部过程。

四、引擎切换(可选)

Hippy 3.x的一个重要特性是支持了多引擎的便捷切换,目前,可切换的引擎有两个,一是布局引擎,二是JS引擎。默认配置下,Hippy使用布局引擎是Taitank,JS引擎是iOS系统内置的JavaScriptCore

如需使用其他布局引擎,如Yoga,或使用其他JS引擎,如V8,可参考如下指引调整Hippy接入配置。

Hippy3.x提供了iOS环境下默认的v8引擎实现,如需使用其他JS引擎需用户自行实现相关napi接口。

4.1 切换JS引擎

如需使用V8引擎,在Podfile文件中添加如下环境变量即可:

ruby
ENV['js_engine'] = 'v8'

修改后的Podfile应该看起来像这样:

text
#use_frameworks!
platform :ios, '11.0'
ENV['js_engine'] = 'v8' #切换为V8引擎

# TargetName大概率是您的项目名称
target TargetName do

    pod 'hippy', 'your_specified_version'

end

之后,重新执行pod install命令更新项目依赖即可。

如需使用其他第三方JS引擎,需要做如下操作:

1.修改Podfile配置为第三方JS引擎

将Podfile中的js_engine环境变量配置为other,这样在拉取代码时,jsc或者v8的代码将不会被添加到工程中。

ruby
ENV['js_engine'] = 'other'

Hippy3.0中使用napi抽象了不同JS引擎的接口。其中,JSC与V8的接口进行了实现。用户若使用JSC或者V8,可直接切换,Hippy默认进行了实现。

2.自行实现napi抽象接口

napi将js引擎接口抽象化,由js driver层调用。接入方自行实现napi接口,即可实现对第三方JS引擎的支持。

napi文件位于 /driver/js/napi* 目录下。

3.将实现文件添加到工程中

接入方自行将对应的napi实现文件添加到工程中。

4.2 切换布局引擎

用户若想使用Yoga布局引擎,直接在Podfile文件中指定layout_engine为Yoga即可:

ruby
ENV['layout_engine'] = 'Yoga'

之后,重新执行pod install命令更新项目依赖即可。

Ohos

注:以下文档都是假设您已经具备一定的 Ohos 开发经验。


前期准备

  • 已经安装 DevEco Studio 最新版本

Demo 体验

  • Ohos Har Demo:Har 包方式依赖 Hippy。 体验方法:DevEco 打开 hippy 项目根目录运行 entry_har。
  • Ohos Demo:源码依赖 Hippy。体验方法:DevEco 打开 hippy 项目根目录直接运行 entry。

注:一定是打开 Hippy 项目根目录,不是 Demo 的根目录

接入方式一:Har包快速接入

1. 创建一个 Ohos 工程

2. Har 包集成

  • 配置 oh-package.json5,依赖 Hippy har 包

依赖远程 ohpm 上 Har 包:

json
 "dependencies": {
   "hippy": "3.3.2"
 }

或者依赖本地 Har 包:

json
 "dependencies": {
   "hippy": "file:./libs/hippy.har"
 }
  • Hippy har包产物构建方法:
    • DevEco Studio 打开 Hippy 根目录
    • DevEco Studio 里 Build Mode 选择 release 或 debug
    • DevEco Studio 里选择 Hippy 模块下文件,比如选择 /framework/ohos/src/main/cpp/CMakeLists.txt
    • DevEco Studio 菜单里 Build - Make Module 'hippy'
    • 目录 /framework/ohos/build/default/outputs/default/ 里生成 hippy.har

3. 初始化代码

  • 获取 libhippy.so 接口对象和 UIAbility context

    TypeScript
    import libHippy from 'libhippy.so' // libhippy.so下面可能会有红线提示,可忽略
    AppStorage.setOrCreate("libHippy", libHippy)
    AppStorage.setOrCreate("abilityContext", this.context)
    AppStorage.setOrCreate("mainWindow", mainWindow)
    

注:App 直接集成 Hippy,context 使用 UIAbility context;如果 App 在一个模块里集成 Hippy,js 等资源也集成在模块里,context 使用 getContext().createModuleContext("moduleName"),否则会找不到 js 等资源。

  • 创建 HippyEngine、初始化 HippyEngine、加载业务 bundle

    TypeScript
    this.hippyEngine = createHippyEngine(params)
    this.hippyEngine.initEngine()
    this.hippyEngine?.loadModule()
    

注:loadModule 需要在 initEngine 成功后调用,即回调结果返回 EngineInitStatus.STATUS_OK 后

  • 组装 HippyRoot 组件
TypeScript
 HippyRoot({
     hippyEngine: this.hippyEngine,
     rootViewWrapper: this.rootViewWrapper,
     onRenderException: (exception: HippyException) => {
       this.exception = `${exception.message}\n${exception.stack}`
     },
 })

4. 销毁代码

Hippy页面退出时,需要释放资源。 destroyModule 用来释放对应 loadModule 的页面资源,destroyEngine 用来释放对应 initEngine 的引擎环境资源。 一定要先 destroyModule,返回后再 destroyEngine。

TypeScript
 hippyEngine?.destroyModule(rootId, () => {
   hippyEngine?.destroyEngine();
 });

注:确保这里 this.hippyEngine 和 this.rootViewWrapper 是有效值

具体可以参考 Har Demo 工程中 EntryAbility.ets Index.ets 实现

接入方式二:源码接入

源码接入主要为了方便在 App 项目里直接调试 Hippy 代码(c++ 和 ets 代码)。

1. 创建一个 Ohos 工程

2. Hippy 代码集成

  • 拉取 hippy 代码到项目里(比如:根目录下,IDE 限制 Hippy 源代码一定要在依赖 Hippy 的项目/模块的目录或子目录里,否则编译会报ets文件路径无法解决的错误)

https://github.com/Tencent/Hippy.git,分支:main

  • 配置 oh-package.json5,依赖 Hippy 文件目录
json
 "dependencies": {
    "hippy": "file:../Hippy/framework/ohos/"
 }

3. Hippy C++ 代码编译配置

  • 如果业务模块没有使用 C++,需 build-profile.json5 里配置使用,如下
json
 "externalNativeOptions": {
   "path": "./src/main/cpp/CMakeLists.txt",
   "arguments": "",
   "cppFlags": "",
 },
  • CMakeLists.txt 内容如下
cmake
cmake_minimum_required(VERSION 3.14)
project(hippy)

set(BIZ_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../")
set(HIPPY_ROOT_DIR "${BIZ_ROOT_DIR}/Hippy_src/framework/ohos/")
set(HIPPY_IMPL_CPP_DIR "${HIPPY_ROOT_DIR}/src/main/cpp/impl")

add_subdirectory("${HIPPY_IMPL_CPP_DIR}" ./hippy_impl)

add_library(${PROJECT_NAME} SHARED

)

target_link_libraries(${PROJECT_NAME} PUBLIC hippy_impl)

set(SOURCE_SET
 )
set(PUBLIC_SOURCE_SET
 )
target_sources(${PROJECT_NAME} PRIVATE ${SOURCE_SET} PUBLIC ${PUBLIC_SOURCE_SET})

4. 初始化代码

  • 获取 libhippy.so 接口对象和 UIAbility context

    TypeScript
    import libHippy from 'libhippy.so'
    AppStorage.setOrCreate("libHippy", libHippy)
    AppStorage.setOrCreate("abilityContext", this.context)
    AppStorage.setOrCreate("mainWindow", mainWindow)
    
  • 创建 HippyEngine、初始化 HippyEngine、加载业务 bundle

    TypeScript
    this.hippyEngine = createHippyEngine(params)
    this.hippyEngine.initEngine()
    this.hippyEngine?.loadModule()
    
  • 组装 HippyRoot 组件

TypeScript
 HippyRoot({
     hippyEngine: this.hippyEngine,
     rootViewWrapper: this.rootViewWrapper,
     onRenderException: (exception: HippyException) => {
       this.exception = `${exception.message}\n${exception.stack}`
     },
 })

5. 销毁代码

Hippy页面退出时,需要释放资源。 destroyModule 用来释放对应 loadModule 的页面资源,destroyEngine 用来释放对应 initEngine 的引擎环境资源。 一定要先 destroyModule,返回后再 destroyEngine。

TypeScript
 hippyEngine?.destroyModule(rootId, () => {
   hippyEngine?.destroyEngine();
 });

具体可以参考 Demo 工程中 EntryAbility.ets 等实现

接入方式三:定制场景接入

  • 对于需要直接依赖 hippy c++ 代码编译使用的定制场景,可参考 Demo 工程中 CMakeLists.txt 说明

Voltron/Flutter

注:以下文档都是假设您已经具备一定的 Flutter 开发经验。

这篇教程,讲述了如何将 Hippy 集成到 Flutter 工程。


前期准备

  • 已经安装了 Flutter version>=3.0 并配置了环境变量

Demo 体验

若想快速体验,可以直接基于我们的 Voltron Demo 来开发,我们提供以下两种 Demo

  • 如果您的应用完全通过 Flutter 进行开发,可以参考flutter_proj,3.0正式发布前,请使用 flutter_proj

  • 如果您希望将 Voltron 集成进您的原生 IOSAndroid 应用,可以使用 flutter module 进行集成

注意,使用 flutter_module 方式进行开发时,原生工程和 Flutter 工程在两个目录,上面所提到的 android-projIOSProj 均需要配合 flutter_module进行使用,3.0正式发布前,请使用 flutter_proj

快速接入

如果您的应用完全通过 Flutter 进行开发

  1. 创建一个 Flutter 工程

  2. Pub 集成

    pubspec.yaml 中添加 Voltron 依赖

    yaml
    dependencies:
      voltron: ^0.0.1
    
  3. 本地集成(可选)

    1. 克隆 Hippy 源码

      shell
      git clone https://github.com/Tencent/Hippy.git
      

      注意使用相应的分支及tag,未合入主干前,请使用v3.0-dev分支

    2. 打开 Flutter 工程根目录下的 pubspec.yaml

      dependencies 下添加 voltron 依赖

      yaml
      voltron:
        path: Hippy路径/framework/voltron
      
  4. 安装依赖

    shell
    flutter pub get
    
  5. 使用 Voltron

    建议参考flutter_proj,3.0正式发布前,请使用 flutter_proj

    Pub 集成方式在 Android 平台默认支持 arm64-v8aarmeabi-v7a,如需支持 x86x86_64,请使用本地集成,iOS 无影响。

    需要注意,如果 debugMode 为YES的情况下,会忽略所有参数,直接使用 npm 本地服务加载测试 bundle,

如果您希望将 Voltron 集成进您的原生 IOSAndroid 应用

  1. 使用该方式进行集成时,要首先集成 Flutter Module,该部分可直接参考官网Add Flutter to an existing app

  2. 后续流程与完全通过 Flutter 进行开发保持一致即可。也可直接参考我们的Demo工程

Web同构

这篇教程,讲述了如何将 Hippy 集成到 Web 页面中。

不同于 @hippy/react-web 和 @hippy/vue-web 方案,本方案(Web Renderer)不会替换 @hippy/react 和 @hippy/vue,而是将运行在原生环境下的 bundle 原封不动运行到 Web 上,与转译 Web 的方案各有利弊,业务可根据具体场景采用合适的方案


前期准备

  • 模板文件:Web 运行需要一个 HTML 文件作为入口
  • 入口文件:WebRenderer 是作为 Hippy bundle 的一个运行环境,因此不共享入口 JS 文件,应为其创建独立的入口文件

npm script

在 demo 项目中,通过 web:dev 命令启动 WebRenderer 调试服务,通过 web:build 打包编译。

json
  "scripts": {
    "web:dev": "npm run hippy:dev & node ./scripts/env-polyfill.js webpack serve --config ./scripts/hippy-webpack.web-renderer.dev.js",
    "web:build": "node ./scripts/env-polyfill.js
webpack --config ./scripts/hippy-webpack.web-renderer.js"
  }

启动调试

执行 npm run web:dev 启动 WebRenderer 调试,根据 demo 的 webpack 配置,WebRenderer 的 web 服务运行在3000端口,浏览器通过 http://localhost:3000 访问页面。

快速接入

WebRenderer 的执行应符合以下流程:

  1. 导入 WebRenderer:该阶段会初始化 Hippy 代码运行的环境
  2. 加载业务 bundle:这个 bundle 与 Native 侧运行的 bundle 包保持一致
  3. 启动 WebRenderer:该阶段会加载 Hippy 内置组件和模块,也可以加载自定义组件和模块

导入 WebRenderer

以 CDN 方式使用

在模板文件内添加:

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
    <title>Example</title>
  </head>
  <body>
    <div id="root"></div>
    <!-- web renderer cdn url -->
    <!-- Hippy不提供cdn资源管理,需业务自行上传之类 -->
    <script src="//xxx.com/lib/hippy-web-renderer/0.1.1/hippy-web-renderer.js"></script>
    <script src="src/index.ts"></script>
  </body>
</html>

以 NPM 包方式使用

shell
npm install -S @hippy/web-renderer

在入口文件内添加:

javascript
// 1. 导入 web renderer
import { HippyWebEngine, HippyWebModule } from '@hippy/web-renderer';

// 2. 导入业务 bundle 的入口文件,需放在 web renderer 导入之后

// 3. 创建 web engine,如果有业务自定义模块和组件,从此处传入

加载业务 Bundle

加载 bundle 包有多种方式,可根据业务需要灵活选择,只需要确保引入顺序在 WebRenderer 之后即可

在模板文件内引用加载

html
<script src="//xxx.com/lib/hippy-web-renderer/0.1.1/hippy-web-renderer.js"></script>
<!-- 业务 bundle -->
<script src="//xxx.com/hippy-biz/index.bundle.js"></script>
<!-- 入口文件 -->
<script src="src/index.ts"></script>

在入口文件内动态加载

javascript
import { HippyWebEngine } from '@hippy/web-renderer';

const engine = HippyWebEngine.create();

 engine.load('https://xxxx.com/hippy-bundle/index.bundle.js').then(() => {
  engine.start({
    id: 'root',
    name: 'example',
  });
});

业务源码直接引用

javascript
import { HippyCallBack, HippyWebEngine, HippyWebModule, View } from '@hippy/web-renderer';
// 导入业务 bundle 的入口文件,需放在 web renderer 导入之后
import './main';


const engine = HippyWebEngine.create();

启动 WebRenderer

加载完业务 bundle 后,调用相关 API 创建并启动 WebRenderer

js
// 创建 web engine,如果有业务自定义模块和组件,从此处传入
// 如果只使用官方模块和组件,则直接使用 const engine = HippyWebEngine.create() 即可
const engine = HippyWebEngine.create({
  modules: {
    CustomCommonModule,
  },
  components: {
    CustomPageView,
  },
});

// 启动 web renderer
engine.start({
  // 挂载的 dom id
  id: 'root',
  // 模块名
  name: 'module-name',
  // 模块启动参数,业务自定义,
  // hippy-react 可以从 入口文件props里获取,hippy-vue可以从 app.$options.$superProps 里获取
  params: {
    path: '/home',
    singleModule: true,
    isSingleMode: true,
    business: '',
    data: { },
  },
});