You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by ky...@apache.org on 2020/03/12 13:00:21 UTC

[incubator-weex] branch master updated: Refactor: Code structure for eagle (#3161)

This is an automated email from the ASF dual-hosted git repository.

kyork pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-weex.git


The following commit(s) were added to refs/heads/master by this push:
     new e3ce661  Refactor: Code structure for eagle (#3161)
e3ce661 is described below

commit e3ce66159d193e3a73cf946653bb48bab06294c1
Author: jianhan-he <41...@users.noreply.github.com>
AuthorDate: Thu Mar 12 21:00:10 2020 +0800

    Refactor: Code structure for eagle (#3161)
    
    * [iOS] fix compile error
    
    * [data-render] seperate plugin added
    
    * [data-render] refine code structure
    
    * [Weex] eagle plugin split with rax and vue and IOS test OK
    
    * [Weex] delete unused source code
    
    * [data-render] cherry-pick https://github.com/apache/incubator-weex/pull/2977/files
    
    * [data-render] fix module / comp not found in plugin
    
    * modify for standard
    
    * modify archs
    
    * add public header file
    
    * fix android import error
    
    * bugfix ios building WeexSDK
    
    Co-authored-by: linghe.lh <li...@alibaba-inc.com>
    Co-authored-by: xujc <hp...@163.com>
    Co-authored-by: pengtao.pt <pe...@alibaba-inc.com>
    Co-authored-by: pingyi.xjc <pi...@alibaba-inc.com>
---
 .../java/org/apache/weex/WXEaglePluginManager.java | 147 +++++
 .../src/main/java/org/apache/weex/WXSDKEngine.java |   4 +
 .../main/java/org/apache/weex/WXSDKInstance.java   |  80 ++-
 .../main/java/org/apache/weex/bridge/WXBridge.java |  23 -
 .../org/apache/weex/bridge/WXBridgeManager.java    | 168 +++---
 .../java/org/apache/weex/bridge/WXEaglePlugin.java | 120 ++++
 .../org/apache/weex/bridge/WXModuleManager.java    |  12 +-
 .../org/apache/weex/performance/WXInstanceApm.java |   6 +-
 .../org/apache/weex/ui/WXComponentRegistry.java    |   5 +-
 ios/sdk/WeexSDK.xcodeproj/project.pbxproj          |  55 +-
 ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m   |  82 +--
 ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m  |  45 +-
 .../WeexSDK/Sources/Manager/WXComponentManager.mm  |   2 +-
 ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h      |  10 -
 ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m      |  97 +--
 .../WeexSDK/Sources/Model/WXSDKInstance_private.h  |   2 +
 .../WXEaglePlugin.h}                               |  31 +-
 .../WeexSDK/Sources/Plugin/WXEaglePluginManager.h  |  51 ++
 .../WeexSDK/Sources/Plugin/WXEaglePluginManager.mm | 181 ++++++
 .../Sources/Protocol/WXAppMonitorProtocol.h        |   2 +-
 ios/sdk/WeexSDK/Sources/Utility/WXVersion.m        |   4 +-
 ios/sdk/WeexSDK/Sources/WeexSDK.h                  |   4 +-
 weex-playground                                    |   2 +-
 weex_core/Source/CMakeLists.txt                    |   1 +
 weex_core/Source/android/wrap/wx_bridge.cpp        |  77 +--
 .../android/jniprebuild/jniheader/WXBridge_jni.h   |  45 --
 weex_core/Source/core/bridge/eagle_bridge.cpp      | 659 ++++++++++++++-------
 weex_core/Source/core/bridge/eagle_bridge.h        | 334 +++++++----
 weex_core/Source/core/bridge/eagle_bridge_ext.cpp  | 112 ++++
 weex_core/Source/core/bridge/eagle_bridge_ext.h    |  52 ++
 .../core/bridge/platform/core_side_in_platform.cpp | 144 +----
 .../core/bridge/script/core_side_in_script.cpp     |  10 +-
 32 files changed, 1651 insertions(+), 916 deletions(-)

diff --git a/android/sdk/src/main/java/org/apache/weex/WXEaglePluginManager.java b/android/sdk/src/main/java/org/apache/weex/WXEaglePluginManager.java
new file mode 100644
index 0000000..a816847
--- /dev/null
+++ b/android/sdk/src/main/java/org/apache/weex/WXEaglePluginManager.java
@@ -0,0 +1,147 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.weex;
+import android.util.Pair;
+import android.text.TextUtils;
+import com.alibaba.fastjson.JSONObject;
+import org.apache.weex.adapter.IWXUserTrackAdapter;
+import org.apache.weex.bridge.ModuleFactory;
+import org.apache.weex.bridge.WXEaglePlugin;
+import org.apache.weex.common.WXRenderStrategy;
+import org.apache.weex.ui.IFComponentHolder;
+import org.apache.weex.utils.WXLogUtils;
+import org.apache.weex.utils.WXSoInstallMgrSdk;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class WXEaglePluginManager {
+  private static final String LOG_TAG = "WXEaglePluginManager";
+
+  private static class InstHolder {
+
+    private static final WXEaglePluginManager INST = new WXEaglePluginManager();
+  }
+
+  private Map<String, WXEaglePlugin> mPluginMap = new ConcurrentHashMap<>();
+
+  private Map<String, Pair<IFComponentHolder, Map<String, Object>>> mCompCache = new ConcurrentHashMap<>();
+  private Map<String, Pair<ModuleFactory, Boolean>> mModuleCache = new ConcurrentHashMap<>();
+
+  public static WXEaglePluginManager getInstance() {
+    return InstHolder.INST;
+  }
+
+  private WXEaglePluginManager() {
+  }
+
+  public void register(WXEaglePlugin plugin) {
+    if (plugin == null || TextUtils.isEmpty(plugin.getPluginName())) {
+      return;
+    }
+    WXEaglePlugin old = mPluginMap.put(plugin.getPluginName(), plugin);
+    //If plugin register is delayed.
+    for (Map.Entry<String, Pair<IFComponentHolder, Map<String, Object>>> entry : mCompCache.entrySet()) {
+      plugin.registerComponent(entry.getKey(),entry.getValue().first, entry.getValue().second);
+    }
+    for (Map.Entry<String, Pair<ModuleFactory, Boolean>> entry : mModuleCache.entrySet()) {
+      plugin.registerModules(entry.getKey(),entry.getValue().first, entry.getValue().second);
+    }
+    if (old != null) {
+      WXLogUtils.w(LOG_TAG, "Register plugin already exist: " + plugin.getPluginName());
+    }
+  }
+
+  void initSo(@SuppressWarnings("SameParameterValue") int version, IWXUserTrackAdapter userTrackAdapter) {
+    for (WXEaglePlugin plugin : mPluginMap.values()) {
+      WXSoInstallMgrSdk.initSo(plugin.getSoLibName(), version, userTrackAdapter);
+    }
+  }
+
+  public WXEaglePlugin getPlugin(String type) {
+    if (type == null) {
+      return null;
+    }
+    return mPluginMap.get(type);
+  }
+
+  public Pair<String, WXEaglePlugin> filterUrl(String url) {
+    for (Map.Entry<String, WXEaglePlugin> entry : mPluginMap.entrySet()) {
+      String result = entry.getValue().isSupportedUrl(url);
+      if (result != null) {
+        //support by this plugin
+        return Pair.create(result, entry.getValue());
+      }
+    }
+    return null;
+  }
+
+  public void registerComponent(String type, IFComponentHolder holder, Map<String, Object> componentInfo) {
+    mCompCache.put(type, Pair.create(holder, componentInfo));
+    for (WXEaglePlugin plugin : mPluginMap.values()) {
+      plugin.registerComponent(type, holder, componentInfo);
+    }
+  }
+
+  public void registerModule(String moduleName, ModuleFactory factory, boolean global) {
+    mModuleCache.put(moduleName, Pair.create(factory, global));
+    for (WXEaglePlugin plugin : mPluginMap.values()) {
+      plugin.registerModules(moduleName, factory, global);
+    }
+  }
+
+  public boolean callEagleTaskFromWeex(String type, String task, JSONObject option) {
+    boolean support = false;
+    if (TextUtils.isEmpty(type)) {
+      for (WXEaglePlugin plugin : mPluginMap.values()) {
+        support = support || plugin.callEagleTaskFromWeex(task, option);
+      }
+    } else {
+      WXEaglePlugin plugin = getPlugin(type);
+      if (plugin != null) {
+        support = plugin.callEagleTaskFromWeex(task, option);
+      }
+    }
+    return support;
+  }
+
+  //TODO(Eagle) remove later
+  static String getPluginName(WXRenderStrategy strategy) {
+    if (strategy == WXRenderStrategy.DATA_RENDER) {
+      return "EagleVue";
+    } else if (strategy == WXRenderStrategy.DATA_RENDER_BINARY) {
+      return "EagleRax";
+    } else {
+      return null;
+    }
+  }
+
+  //TODO(Eagle) remove later
+  static WXRenderStrategy getRenderStrategyByPlugin(String name) {
+    switch (name) {
+      case "EagleVue":
+        return WXRenderStrategy.DATA_RENDER;
+      case "EagleRax":
+        return WXRenderStrategy.DATA_RENDER_BINARY;
+    }
+    return null;
+  }
+
+}
diff --git a/android/sdk/src/main/java/org/apache/weex/WXSDKEngine.java b/android/sdk/src/main/java/org/apache/weex/WXSDKEngine.java
index ed1cda6..1886bcb 100644
--- a/android/sdk/src/main/java/org/apache/weex/WXSDKEngine.java
+++ b/android/sdk/src/main/java/org/apache/weex/WXSDKEngine.java
@@ -228,6 +228,10 @@ public class WXSDKEngine implements Serializable {
             WXSoInstallMgrSdk.initSo(libraryName, version, userTrackAdapter);
           }
         }
+
+        // Init so for each eagle plugin, which will register DataRenderHandler to EagleBridge in JNI_OnLoad
+        WXEaglePluginManager.getInstance().initSo(version, userTrackAdapter);
+
         if (!mIsSoInit) {
           WXExceptionUtils.commitCriticalExceptionRT(null,
                   WXErrorCode.WX_KEY_EXCEPTION_SDK_INIT,
diff --git a/android/sdk/src/main/java/org/apache/weex/WXSDKInstance.java b/android/sdk/src/main/java/org/apache/weex/WXSDKInstance.java
index 3779727..5ddcd08 100644
--- a/android/sdk/src/main/java/org/apache/weex/WXSDKInstance.java
+++ b/android/sdk/src/main/java/org/apache/weex/WXSDKInstance.java
@@ -34,12 +34,13 @@ import android.support.annotation.RestrictTo;
 import android.support.annotation.RestrictTo.Scope;
 import android.support.annotation.WorkerThread;
 import android.support.v4.util.ArrayMap;
+import android.util.Pair;
 import android.text.TextUtils;
-import android.util.Log;
 import android.view.Menu;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ScrollView;
+
 import com.alibaba.fastjson.JSONObject;
 import org.apache.weex.adapter.IDrawableLoader;
 import org.apache.weex.adapter.IWXConfigAdapter;
@@ -53,6 +54,7 @@ import org.apache.weex.bridge.EventResult;
 import org.apache.weex.bridge.NativeInvokeHelper;
 import org.apache.weex.bridge.SimpleJSCallback;
 import org.apache.weex.bridge.WXBridgeManager;
+import org.apache.weex.bridge.WXEaglePlugin;
 import org.apache.weex.bridge.WXModuleManager;
 import org.apache.weex.bridge.WXParams;
 import org.apache.weex.common.Constants;
@@ -106,6 +108,9 @@ import java.util.PriorityQueue;
 import java.util.concurrent.ConcurrentHashMap;
 import org.apache.weex.bridge.WXBridgeManager.BundType;
 
+import static org.apache.weex.common.WXErrorCode.WX_ERR_RELOAD_PAGE;
+import static org.apache.weex.http.WXHttpUtil.KEY_USER_AGENT;
+
 
 /**
  * Each instance of WXSDKInstance represents an running weex instance.
@@ -164,7 +169,7 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
   /**
    * bundle type
    */
-  public BundType bundleType;
+  public WXBridgeManager.BundType bundleType;
   public long mRenderStartNanos;
   public int mExecJSTraceId = WXTracing.nextId();
 
@@ -183,6 +188,7 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
    * Render strategy.
    */
   private WXRenderStrategy mRenderStrategy = WXRenderStrategy.APPEND_ASYNC;
+  private String mEaglePluginName;
 
   private boolean mDisableSkipFrameworkInit = false;
 
@@ -222,6 +228,8 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
    * */
   private boolean mAutoAdjustDeviceWidth = WXEnvironment.AUTO_ADJUST_ENV_DEVICE_WIDTH;
 
+  private volatile WXEaglePlugin mEaglePlugin;
+
   public  List<JSONObject> getComponentsExceedGPULimit(){return componentsInfoExceedGPULimit;}
   @RestrictTo(Scope.LIBRARY)
   public void setComponentsInfoExceedGPULimit(JSONObject component){
@@ -834,7 +842,7 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
                       String jsonInitData,
                       WXRenderStrategy flag){
     isPreInit = true;
-    mRenderStrategy = flag;
+    setRenderStrategy(flag);
     Map<String, Object> renderOptions = options;
     if (renderOptions == null) {
       renderOptions = new HashMap<>();
@@ -844,12 +852,22 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
     WXSDKManager.getInstance().createInstance(this, new Script(script), renderOptions, jsonInitData);
   }
 
+  private void setRenderStrategy(WXRenderStrategy flag) {
+    mRenderStrategy = flag;
+    setEaglePlugin(WXEaglePluginManager.getPluginName(mRenderStrategy));
+  }
+
+  private void setEaglePlugin(String plugin){
+    mEaglePluginName = plugin;
+    mEaglePlugin = WXEaglePluginManager.getInstance().getPlugin(mEaglePluginName);
+  }
+
   public void preDownLoad(String url,
                           Map<String, Object> options,
                           String jsonInitData,
                           WXRenderStrategy flag){
     this.isPreDownLoad =true;
-    mRenderStrategy = flag;
+    setRenderStrategy(flag);
     mApmForInstance.isReady = false;
     renderByUrl(url,url,options,jsonInitData,flag);
   }
@@ -865,7 +883,7 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
     }
 
     LogDetail logDetail = mTimeCalculator.createLogDetail("renderInternal");
-    mRenderStrategy = flag;
+    setRenderStrategy(flag);
 
     //some case ,from render(template),but not render (url)
     if (!mApmForInstance.hasInit()){
@@ -961,7 +979,7 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
           if(containerView instanceof ViewGroup) {
             if(0 == ((ViewGroup) containerView).getChildCount()) {
               if(wxJscProcessManager.withException(WXSDKInstance.this)) {
-                onJSException(String.valueOf(WXErrorCode.WX_ERR_RELOAD_PAGE),"jsc reboot","jsc reboot");
+                onJSException(String.valueOf(WX_ERR_RELOAD_PAGE),"jsc reboot","jsc reboot");
               }
               if(!createInstanceHeartBeat) {
                   WXBridgeManager.getInstance().callReportCrashReloadPage(mInstanceId, null);
@@ -1001,15 +1019,27 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
 
 
   public boolean skipFrameworkInit(){
-    return isDataRender() && !mDisableSkipFrameworkInit;
+    return getEaglePlugin() != null && getEaglePlugin().isSkipFrameworkInit(getInstanceId()) && !mDisableSkipFrameworkInit;
   }
 
   private boolean isDataRender() {
-    return getRenderStrategy() == WXRenderStrategy.DATA_RENDER_BINARY || getRenderStrategy() == WXRenderStrategy.DATA_RENDER;
+    return getEaglePlugin() != null;
+  }
+
+  private String  filterUrlByEaglePlugin(String url){
+    Pair<String, WXEaglePlugin> eaglePluginPair = WXEaglePluginManager.getInstance().filterUrl(url);
+    if (eaglePluginPair != null){
+      url = eaglePluginPair.first;
+      mEaglePlugin = eaglePluginPair.second;
+      mEaglePluginName = mEaglePlugin.getPluginName();
+      mRenderStrategy = WXEaglePluginManager.getRenderStrategyByPlugin(mEaglePluginName);
+      return url;
+    }
+    return null;
   }
 
   private void renderByUrlInternal(String pageName,
-                                   final String url,
+                                   String url,
                                    Map<String, Object> options,
                                    final String jsonInitData,
                                    WXRenderStrategy flag) {
@@ -1020,11 +1050,18 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
     ensureRenderArchor();
     pageName = wrapPageName(pageName, url);
     mBundleUrl = url;
-    mRenderStrategy = flag;
+    setRenderStrategy(flag);
     if(WXSDKManager.getInstance().getValidateProcessor()!=null) {
       mNeedValidate = WXSDKManager.getInstance().getValidateProcessor().needValidate(mBundleUrl);
     }
 
+    //process eagle, overwrite plugin & renderStrategy.
+    String eagleUrl = filterUrlByEaglePlugin(url);
+    if (eagleUrl != null){
+      url = eagleUrl;
+      flag = mRenderStrategy;
+    }
+
     Map<String, Object> renderOptions = options;
     if (renderOptions == null) {
       renderOptions = new HashMap<>();
@@ -1047,16 +1084,6 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
       return;
     }
 
-    boolean is_wlasm = false;
-    if (uri != null && uri.getPath()!=null) {
-      if(uri.getPath().endsWith(".wlasm")){
-        is_wlasm =  true;
-      }
-    }
-    if (is_wlasm){
-      flag = WXRenderStrategy.DATA_RENDER_BINARY;
-    }
-
     IWXHttpAdapter adapter = WXSDKManager.getInstance().getIWXHttpAdapter();
 
     WXRequest wxRequest = new WXRequest();
@@ -1663,6 +1690,7 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
     if (!isNewFsEnd){
       getApmForInstance().arriveNewFsRenderTime();
     }
+    //record interactive time here if render_container is wrap_content
     if (!getApmForInstance().stageMap.containsKey(WXInstanceApm.KEY_PAGE_STAGES_INTERACTION)){
       getApmForInstance().arriveInteraction(getRootComponent());
     }
@@ -2500,4 +2528,16 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
   public void setPageDirty(boolean mPageDirty) {
     this.mPageDirty = mPageDirty;
   }
+
+  public WXEaglePlugin getEaglePlugin() {
+    return mEaglePlugin;
+  }
+
+  public String getEaglePluginName() {
+    return mEaglePluginName;
+  }
+
+  public boolean isUsingEaglePlugin() {
+    return mEaglePlugin != null;
+  }
 }
diff --git a/android/sdk/src/main/java/org/apache/weex/bridge/WXBridge.java b/android/sdk/src/main/java/org/apache/weex/bridge/WXBridge.java
index 05fd44d..3ea30f5 100755
--- a/android/sdk/src/main/java/org/apache/weex/bridge/WXBridge.java
+++ b/android/sdk/src/main/java/org/apache/weex/bridge/WXBridge.java
@@ -74,14 +74,6 @@ import java.util.Map;
 
   public native String nativeExecJSOnInstance(String instanceId, String script, int type);
 
-  public native void nativeFireEventOnDataRenderNode(String instanceId, String ref, String type, String data, String domChanges);
-
-  public native void nativeInvokeCallbackOnDataRender(String instanceId, String callbackId, String data, boolean keepAlive);
-
-  public native void nativeRegisterModuleOnDataRenderNode( String data);
-
-  public native void nativeRegisterComponentOnDataRenderNode( String data);
-
   private native void nativeTakeHeapSnapshot(String filename);
 
   private native void nativeBindMeasurementToRenderObject(long ptr);
@@ -911,21 +903,6 @@ import java.util.Map;
     }
   }
 
-  public void fireEventOnDataRenderNode(String instanceId, String ref, String type, String data, String domChanges) {
-    nativeFireEventOnDataRenderNode(instanceId,ref,type,data, domChanges);
-  }
-
-  public void invokeCallbackOnDataRender(String instanceId, String callbackId, String data, boolean keepAlive) {
-    nativeInvokeCallbackOnDataRender(instanceId,callbackId,data, keepAlive);
-  }
-
-  public void registerModuleOnDataRenderNode(String data) {
-    nativeRegisterModuleOnDataRenderNode(data);
-  }
-
-  public void registerComponentOnDataRenderNode(String data) {
-    nativeRegisterComponentOnDataRenderNode(data);
-  }
   public void reloadPageLayout(String instanceId){
     nativeReloadPageLayout(instanceId);
   }
diff --git a/android/sdk/src/main/java/org/apache/weex/bridge/WXBridgeManager.java b/android/sdk/src/main/java/org/apache/weex/bridge/WXBridgeManager.java
index c7873c3..801f84f 100755
--- a/android/sdk/src/main/java/org/apache/weex/bridge/WXBridgeManager.java
+++ b/android/sdk/src/main/java/org/apache/weex/bridge/WXBridgeManager.java
@@ -110,15 +110,7 @@ import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Stack;
+import java.util.*;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Pattern;
@@ -530,7 +522,7 @@ public class WXBridgeManager implements Callback, BactchExecutor {
   /**
    * Set current Instance
    *
-   * @param instanceId {@link WXSDKInstance#mInstanceId}
+   * @param instanceId {@link WXSDKInstance#getInstanceId()}
    */
   public synchronized void setStackTopInstance(final String instanceId) {
     post(new Runnable() {
@@ -726,7 +718,7 @@ public class WXBridgeManager implements Callback, BactchExecutor {
   /**
    * Dispatch the native task to be executed.
    *
-   * @param instanceId {@link WXSDKInstance#mInstanceId}
+   * @param instanceId {@link WXSDKInstance#getInstanceId()}
    * @param tasks      tasks to be executed
    * @param callback   next tick id
    */
@@ -1291,36 +1283,40 @@ public class WXBridgeManager implements Callback, BactchExecutor {
               "fireEvent must be called by main thread");
     }
     WXSDKInstance instance = WXSDKManager.getInstance().getAllInstanceMap().get(instanceId);
-    if (instance != null && (instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER ||
-            instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER_BINARY)) {
-      fireEventOnDataRenderNode(instanceId, ref, type, data, domChanges);
-    } else {
-      if(callback == null) {
-        addJSEventTask(METHOD_FIRE_EVENT, instanceId, params, ref, type, data, domChanges);
-        sendMessage(instanceId, WXJSBridgeMsgType.CALL_JS_BATCH);
-      }else{
-        asyncCallJSEventWithResult(callback, METHD_FIRE_EVENT_SYNC, instanceId, params, ref, type, data, domChanges);
+    if (instance != null && instance.isUsingEaglePlugin()) {
+      int mode = instance.getEaglePlugin().isSupportFireEvent(instanceId);
+      if (mode == WXEaglePlugin.NOT_SUPPORT){
+        return;
+      }
+      fireEventOnDataRenderNode(instance.getEaglePlugin(), instanceId, ref, type, data, domChanges);
+      if (mode == WXEaglePlugin.EAGLE_ONLY){
+        return;
       }
+      //assert mode == WXEaglePlugin.EAGLE_AND_SCRIPT
+    }
+
+    if (callback == null) {
+      addJSEventTask(METHOD_FIRE_EVENT, instanceId, params, ref, type, data, domChanges);
+      sendMessage(instanceId, WXJSBridgeMsgType.CALL_JS_BATCH);
+    } else {
+      asyncCallJSEventWithResult(callback, METHD_FIRE_EVENT_SYNC, instanceId, params, ref, type, data, domChanges);
     }
   }
 
-  private void fireEventOnDataRenderNode(final String instanceId, final String ref,
+  private void fireEventOnDataRenderNode(final WXEaglePlugin eaglePlugin, final String instanceId, final String ref,
                                          final String type, final Map<String, Object> data, final Map<String, Object> domChanges) {
     mJSHandler.postDelayed(WXThread.secure(new Runnable() {
       @Override
       public void run() {
         try {
-          WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
           long start = System.currentTimeMillis();
           if (WXEnvironment.isApkDebugable()) {
             WXLogUtils.d("fireEventOnDataRenderNode >>>> instanceId:" + instanceId
                 + ", data:" + data);
           }
-          if (mWXBridge instanceof WXBridge) {
-            ((WXBridge) mWXBridge).fireEventOnDataRenderNode(instanceId, ref, type,
-                (data == null || data.isEmpty()) ? "{}" : JSON.toJSONString(data),
-                (domChanges == null || domChanges.isEmpty()) ? "{}" : JSON.toJSONString(domChanges));
-          }
+          eaglePlugin.fireEvent(instanceId, ref, type,
+              (data == null || data.isEmpty()) ? "{}" : JSON.toJSONString(data),
+              (domChanges == null || domChanges.isEmpty()) ? "{}" : JSON.toJSONString(domChanges));
           WXLogUtils.renderPerformanceLog("fireEventOnDataRenderNode", System.currentTimeMillis() - start);
         } catch (Throwable e) {
           String err = "[WXBridgeManager] fireEventOnDataRenderNode " + WXLogUtils.getStackTrace(e);
@@ -1382,20 +1378,29 @@ public class WXBridgeManager implements Callback, BactchExecutor {
   void callbackJavascript(final String instanceId, final String callback,
                           final Object data, boolean keepAlive) {
     if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(callback)
-            || mJSHandler == null) {
+        || mJSHandler == null) {
       return;
     }
 
     WXSDKInstance instance = WXSDKManager.getInstance().getAllInstanceMap().get(instanceId);
-    if (instance != null && (instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER_BINARY)) {
-      callbackJavascriptOnDataRender(instanceId, callback, data, keepAlive);
-    } else {
-      addJSTask(METHOD_CALLBACK, instanceId, callback, data, keepAlive);
-      sendMessage(instanceId, WXJSBridgeMsgType.CALL_JS_BATCH);
+    if (instance != null && instance.isUsingEaglePlugin()) {
+      int mode = instance.getEaglePlugin().isSupportJSCallback(instanceId);
+      if (mode == WXEaglePlugin.NOT_SUPPORT) {
+        return;
+      }
+      callbackJavascriptOnDataRender(instance.getEaglePlugin(), instanceId, callback, data, keepAlive);
+      if (mode == WXEaglePlugin.EAGLE_ONLY) {
+        return;
+      }
+      //assert mode == WXEaglePlugin.EAGLE_AND_SCRIPT
     }
+
+
+    addJSTask(METHOD_CALLBACK, instanceId, callback, data, keepAlive);
+    sendMessage(instanceId, WXJSBridgeMsgType.CALL_JS_BATCH);
   }
 
-  void callbackJavascriptOnDataRender(final String instanceId, final String callback, final Object data, final boolean keepAlive){
+  void callbackJavascriptOnDataRender(final WXEaglePlugin eaglePlugin, final String instanceId, final String callback, final Object data, final boolean keepAlive){
     mJSHandler.postDelayed(WXThread.secure(new Runnable() {
       @Override
       public void run() {
@@ -1406,9 +1411,7 @@ public class WXBridgeManager implements Callback, BactchExecutor {
             WXLogUtils.d("callbackJavascriptOnDataRender >>>> instanceId:" + instanceId
                 + ", data:" + data_str);
           }
-          if (mWXBridge instanceof WXBridge) {
-            ((WXBridge) mWXBridge).invokeCallbackOnDataRender(instanceId, callback,data_str ,keepAlive);
-          }
+          eaglePlugin.invokeJSCallback(instanceId, callback, data_str, keepAlive);
           WXLogUtils.renderPerformanceLog("callbackJavascriptOnDataRender", System.currentTimeMillis() - start);
         } catch (Throwable e) {
           String err = "[WXBridgeManager] callbackJavascriptOnDataRender " + WXLogUtils.getStackTrace(e);
@@ -1655,8 +1658,20 @@ public class WXBridgeManager implements Callback, BactchExecutor {
         }
         WXJSObject instanceIdObj = new WXJSObject(WXJSObject.String,
                 instance.getInstanceId());
-        WXJSObject instanceObj = new WXJSObject(WXJSObject.String,
-                template.getContent());
+        WXJSObject instanceObj;
+        WXJSObject scriptType;
+        if (TextUtils.isEmpty(template.getContent())){
+          //byte[]
+          instanceObj = new WXJSObject(WXJSObject.String,
+              template.getBinary());
+          scriptType = new WXJSObject(WXJSObject.String, "binary");
+        } else {
+          //String
+          instanceObj = new WXJSObject(WXJSObject.String,
+              template.getContent());
+          scriptType = new WXJSObject(WXJSObject.NUMBER, "string");
+        }
+
 
         Object extraOption = null;
         if(options != null && options.containsKey("extraOption")) {
@@ -1697,14 +1712,15 @@ public class WXBridgeManager implements Callback, BactchExecutor {
 
         // When render strategy is data_render, put it into options. Others keep null.
         WXJSObject renderStrategy = null;
-        if (instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER) {
-          renderStrategy = new WXJSObject(WXJSObject.String, WXRenderStrategy.DATA_RENDER.getFlag());
-        } else if (instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER_BINARY) {
-          renderStrategy = new WXJSObject(WXJSObject.String, WXRenderStrategy.DATA_RENDER_BINARY.getFlag());
-          // In DATA_RENDER_BINARY strategy script is binary
-          instanceObj.data = template.getBinary();
-        }else if (instance.getRenderStrategy() == WXRenderStrategy.JSON_RENDER) {
-             renderStrategy = new WXJSObject(WXJSObject.String, WXRenderStrategy.JSON_RENDER.getFlag());
+        if (instance.isUsingEaglePlugin()) {
+          //Eagle use plugin name as renderStrategy
+          renderStrategy = new WXJSObject(WXJSObject.String, instance.getEaglePluginName());
+        } else if (instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER_BINARY || instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER) {
+          //todo just for compat
+          //using eagle mode without eagle plugin, will report exception in c if no plugin was found.
+          renderStrategy = new WXJSObject(WXJSObject.String, "DATA_RENDER");
+        } else if (instance.getRenderStrategy() == WXRenderStrategy.JSON_RENDER) {
+          renderStrategy = new WXJSObject(WXJSObject.String, WXRenderStrategy.JSON_RENDER.getFlag());
         }
 
         WXJSObject[] args = {instanceIdObj, instanceObj, optionsObj,
@@ -1723,13 +1739,17 @@ public class WXBridgeManager implements Callback, BactchExecutor {
           return;
         }
         if (type == BundType.Vue || type == BundType.Rax
+                || instance.isUsingEaglePlugin()
+                || instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER_BINARY //Todo only for compat when plugin not registered
                 || instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER
-                || instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER_BINARY
                 || instance.getRenderStrategy() == WXRenderStrategy.JSON_RENDER) {
           instance.getApmForInstance().onStage("wxBeforeInvokeCreateInstanceContext");
 
           WXLogUtils.d("Instance " + instance.getInstanceId() + " Render in SandBox Mode And Render Type is "
                   + type + " Render Strategy is " + instance.getRenderStrategy());
+          //extra args for create instance.
+          args = Arrays.copyOf(args,args.length+1);
+          args[args.length -1 ] = scriptType;
 
           int ret = invokeCreateInstanceContext(instance.getInstanceId(), null, "createInstanceContext", args, false);
           instance.getApmForInstance().onStage(WXInstanceApm.KEY_PAGE_STAGES_LOAD_BUNDLE_END);
@@ -1947,24 +1967,37 @@ public class WXBridgeManager implements Callback, BactchExecutor {
     }
     final long start = System.currentTimeMillis();
     WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
-    if (instance != null && (instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER_BINARY)) {
-      Pair<Pair<String,Object>, Boolean> data = null;
-      if(args.length!=2 || !(args[0].data instanceof String)
-          || !(args[1].data instanceof String)
-          || (data = extractCallbackArgs((String) args[1].data))==null){
-        WXLogUtils.w("invokeExecJS on data render that is not a callback call");
+
+    if (instance != null && instance.isUsingEaglePlugin()) {
+      final WXEaglePlugin eaglePlugin = instance.getEaglePlugin();
+      int mode = eaglePlugin.isSupportInvokeExecJS(instanceId);
+      if (mode == WXEaglePlugin.NOT_SUPPORT){
         return;
       }
-      callbackJavascriptOnDataRender(instanceId, (String) data.first.first, data.first.second, data.second);
-    } else {
-
       WXThread.secure(new Runnable() {
         @Override
         public void run() {
-          mWXBridge.execJS(instanceId, namespace, function, args);
+          eaglePlugin.invokeExecJS(instanceId, namespace, function,args );
+        }
+      }, instance, "ExecJsEagle").run();
+      if (mode == WXEaglePlugin.EAGLE_ONLY){
+        if (null != instance){
+          long diff = System.currentTimeMillis()-start;
+          instance.getApmForInstance().updateFSDiffStats(WXInstanceApm.KEY_PAGE_STATS_FS_CALL_JS_NUM,1);
+          instance.getApmForInstance().updateFSDiffStats(WXInstanceApm.KEY_PAGE_STATS_FS_CALL_JS_TIME,diff);
+          instance.callJsTime(diff);
         }
-      }, instance, "ExecJs").run();
+        return;
+      }
+      //assert mode == WXEaglePlugin.EAGLE_AND_SCRIPT
     }
+
+    WXThread.secure(new Runnable() {
+      @Override
+      public void run() {
+        mWXBridge.execJS(instanceId, namespace, function, args);
+      }
+    }, instance, "ExecJs").run();
     if (null != instance){
       long diff = System.currentTimeMillis()-start;
       instance.getApmForInstance().updateFSDiffStats(WXInstanceApm.KEY_PAGE_STATS_FS_CALL_JS_NUM,1);
@@ -2449,14 +2482,6 @@ public class WXBridgeManager implements Callback, BactchExecutor {
 
     WXJSObject[] args = {WXWsonJSONSwitch.toWsonOrJsonWXJSObject(modules)};
     String errorMsg = null;
-    try{
-      // TODO use a better way
-      if (mWXBridge instanceof WXBridge) {
-        ((WXBridge) mWXBridge).registerModuleOnDataRenderNode(WXJsonUtils.fromObjectToJSONString(modules));
-      }
-    } catch (Throwable e){
-      WXLogUtils.e("Weex [data_render register err]", e);
-    }
     try {
         if(0 == mWXBridge.execJS("", null, METHOD_REGISTER_MODULES, args)) {
             errorMsg = "execJS error";
@@ -2503,15 +2528,6 @@ public class WXBridgeManager implements Callback, BactchExecutor {
       return;
     }
 
-    try{
-      // TODO use a better way
-      if (mWXBridge instanceof WXBridge) {
-        ((WXBridge) mWXBridge).registerComponentOnDataRenderNode(WXJsonUtils.fromObjectToJSONString(components));
-      }
-    } catch (Throwable e){
-      WXLogUtils.e("Weex [data_render register err]", e);
-    }
-
     WXJSObject[] args = {WXWsonJSONSwitch.toWsonOrJsonWXJSObject(components)};
     String errorMsg = null;
     try {
diff --git a/android/sdk/src/main/java/org/apache/weex/bridge/WXEaglePlugin.java b/android/sdk/src/main/java/org/apache/weex/bridge/WXEaglePlugin.java
new file mode 100644
index 0000000..44d8128
--- /dev/null
+++ b/android/sdk/src/main/java/org/apache/weex/bridge/WXEaglePlugin.java
@@ -0,0 +1,120 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.weex.bridge;
+import android.support.annotation.NonNull;
+import com.alibaba.fastjson.JSONObject;
+import org.apache.weex.InitConfig;
+import org.apache.weex.ui.IFComponentHolder;
+import java.util.Map;
+public interface WXEaglePlugin {
+  int NOT_SUPPORT  = 0;
+  int EAGLE_ONLY = 1;
+  int EAGLE_AND_SCRIPT  = 2;
+  /**
+   * Called during WXSDKEngine init.
+   *
+   * @return so name of the plugin, which should be loading into {@link InitConfig.Builder#addNativeLibrary}
+   */
+  String getSoLibName();
+  /**
+   * If this kind of plugin support skip js framework on instanceId.
+   */
+  boolean isSkipFrameworkInit(String instanceId);
+  /**
+   * @return If this plugin support lazy load Components & Modules.
+   */
+  boolean isLazyCompAndModuleSupport();
+  /**
+   * @return Name of this plugin.
+   */
+  @NonNull
+  String getPluginName();
+  /**
+   * A filter to intercept url in {@link com.taobao.weex.WXSDKInstance#renderByUrl}.
+   *
+   * @param url Origin weex url in {@link com.taobao.weex.WXSDKInstance#renderByUrl}.
+   *
+   * @return {@code null} if plugin don't support such url.
+   *     <p>
+   *     {@code String} if plugin support such url. Url could be modified. Following process should
+   *     use this value to overwrite old one.
+   */
+  String isSupportedUrl(String url);
+  /**
+   * Called in arbitrary thread
+   *
+   * @param instanceId instanceId of {@code WXSDKInstance}
+   *
+   * @return {@code 0} if not supported.
+   *     {@code 1} if supported and no further call into JsFramework required.
+   *     {@code 2} if supported and further call into JsFramework required.
+   */
+  int isSupportJSCallback(String instanceId);
+  /**
+   * Must called in js-thread.
+   */
+  void invokeJSCallback(String instanceId,
+                        String callbackId,
+                        String data,
+                        boolean keep_alive);
+  /**
+   * Called in arbitrary thread
+   *
+   * @param instanceId instanceId of {@code WXSDKInstance}
+   *
+   * @return {@code 0} if not supported.
+   *     {@code 1} if supported and no further call into JsFramework required.
+   *     {@code 2} if supported and further call into JsFramework required.
+   */
+  int isSupportInvokeExecJS(String instanceId);
+  /**
+   * Must called in js-thread.
+   */
+  void invokeExecJS(final String instanceId, final String namespace, final String function,
+                    final WXJSObject[] args);
+  /**
+   * Called in arbitrary thread
+   *
+   * @param instanceId instanceId of {@code WXSDKInstance}
+   *
+   * @return {@code 0} if not supported.
+   *     {@code 1} if supported and no further call into JsFramework required.
+   *     {@code 2} if supported and further call into JsFramework required.
+   */
+  int isSupportFireEvent(String instanceId);
+  /**
+   * Must called in js-thread.
+   */
+  void fireEvent(String instanceId, String ref, String type, String data, String domChanges);
+  /**
+   * Called in any thread. This method should be thread-safe
+   */
+  void registerModules(final String moduleName, final ModuleFactory factory, final boolean global);
+  /**
+   * Called in any thread. This method should be thread-safe
+   */
+  void registerComponent(final String type, final IFComponentHolder holder, final Map<String, Object> componentInfo);
+  /**
+   * @param task   task name;
+   * @param option options, a JSONObject
+   *
+   * @return true if this task is supported. false else-wise.
+   */
+  boolean callEagleTaskFromWeex(String task, JSONObject option);
+}
\ No newline at end of file
diff --git a/android/sdk/src/main/java/org/apache/weex/bridge/WXModuleManager.java b/android/sdk/src/main/java/org/apache/weex/bridge/WXModuleManager.java
index 25fdbe6..d22f130 100644
--- a/android/sdk/src/main/java/org/apache/weex/bridge/WXModuleManager.java
+++ b/android/sdk/src/main/java/org/apache/weex/bridge/WXModuleManager.java
@@ -24,6 +24,8 @@ import android.text.TextUtils;
 import android.view.Menu;
 
 import com.alibaba.fastjson.JSONArray;
+
+import org.apache.weex.WXEaglePluginManager;
 import org.apache.weex.WXSDKInstance;
 import org.apache.weex.WXSDKManager;
 import org.apache.weex.WXSDKEngine;
@@ -68,11 +70,11 @@ public class WXModuleManager {
   private static Map<String, Map<String, WXModule>> sInstanceModuleMap = new ConcurrentHashMap<>();
 
 
-  public static boolean registerModule(Map<String, ModuleCache> moduleCacheMap) {
+  public static boolean registerModule(Map<String, RegisterCache.ModuleCache> moduleCacheMap) {
     if (moduleCacheMap.isEmpty())
       return true;
 
-    final Iterator<Entry<String, ModuleCache>> iterator = moduleCacheMap.entrySet().iterator();
+    final Iterator<Entry<String, RegisterCache.ModuleCache>> iterator = moduleCacheMap.entrySet().iterator();
     WXBridgeManager.getInstance()
             .postWithName(new Runnable() {
               @Override
@@ -80,8 +82,8 @@ public class WXModuleManager {
                 Map<String, Object> modules = new HashMap<>();
 
                 while (iterator.hasNext()) {
-                  Entry<String, ModuleCache> next = iterator.next();
-                  ModuleCache value = next.getValue();
+                  Entry<String, RegisterCache.ModuleCache> next = iterator.next();
+                  RegisterCache.ModuleCache value = next.getValue();
                   String moduleName = value.name;
                   if (TextUtils.equals(moduleName, WXDomModule.WXDOM)) {
                     WXLogUtils.e("Cannot registered module with name 'dom'.");
@@ -133,7 +135,7 @@ public class WXModuleManager {
       WXLogUtils.e("Cannot registered module with name 'dom'.");
       return false;
     }
-
+    WXEaglePluginManager.getInstance().registerModule(moduleName, factory, global);
     if(RegisterCache.getInstance().cacheModule(moduleName,factory,global)) {
       return true;
     }
diff --git a/android/sdk/src/main/java/org/apache/weex/performance/WXInstanceApm.java b/android/sdk/src/main/java/org/apache/weex/performance/WXInstanceApm.java
index 42de1ea..0be0965 100644
--- a/android/sdk/src/main/java/org/apache/weex/performance/WXInstanceApm.java
+++ b/android/sdk/src/main/java/org/apache/weex/performance/WXInstanceApm.java
@@ -341,8 +341,10 @@ public class WXInstanceApm {
         }
 
         addProperty("wxUseRuntimeApi",WXEnvironment.sUseRunTimeApi);
-        if (instance != null && (instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER
-                || instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER_BINARY)) {
+        if (instance != null && (instance.isUsingEaglePlugin()
+            || instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER_BINARY //todo only for compat.
+            || instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER
+        )) {
             addProperty(KEY_PAGE_PROPERTIES_RENDER_TYPE, WXEnvironment.EAGLE);
         }
         if (null != instance) {
diff --git a/android/sdk/src/main/java/org/apache/weex/ui/WXComponentRegistry.java b/android/sdk/src/main/java/org/apache/weex/ui/WXComponentRegistry.java
index eee9be0..f0d7ed9 100644
--- a/android/sdk/src/main/java/org/apache/weex/ui/WXComponentRegistry.java
+++ b/android/sdk/src/main/java/org/apache/weex/ui/WXComponentRegistry.java
@@ -20,6 +20,7 @@ package org.apache.weex.ui;
 
 import android.text.TextUtils;
 
+import org.apache.weex.WXEaglePluginManager;
 import org.apache.weex.WXSDKManager;
 import org.apache.weex.bridge.WXBridgeManager;
 import org.apache.weex.common.WXException;
@@ -76,7 +77,7 @@ public class WXComponentRegistry {
     if (holder == null || TextUtils.isEmpty(type)) {
       return false;
     }
-
+    WXEaglePluginManager.getInstance().registerComponent(type, holder, componentInfo);
     if(RegisterCache.getInstance().cacheComponent(type,holder,componentInfo)) {
       return true;
     }
@@ -106,7 +107,7 @@ public class WXComponentRegistry {
     return true;
   }
 
-  private static boolean registerNativeComponent(String type, IFComponentHolder holder) throws WXException {
+  static boolean registerNativeComponent(String type, IFComponentHolder holder) throws WXException {
     try {
       holder.loadIfNonLazy();
       sTypeComponentMap.put(type, holder);
diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
index 86f7fdc..470c4ad 100644
--- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
+++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
@@ -325,7 +325,7 @@
 		77E349F8229FE67900B1CDAB /* log_defines.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77E349F6229FE67900B1CDAB /* log_defines.cpp */; };
 		77E659DA1C07F594008B8775 /* WXDomModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 77E659D81C07F594008B8775 /* WXDomModule.h */; };
 		77E659DB1C07F594008B8775 /* WXDomModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 77E659D91C07F594008B8775 /* WXDomModule.m */; };
-		77E659F11C0C3612008B8775 /* WXModuleFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 77E659EF1C0C3612008B8775 /* WXModuleFactory.h */; };
+		77E659F11C0C3612008B8775 /* WXModuleFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 77E659EF1C0C3612008B8775 /* WXModuleFactory.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		77E659F21C0C3612008B8775 /* WXModuleFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 77E659F01C0C3612008B8775 /* WXModuleFactory.m */; };
 		77E65A0D1C155E99008B8775 /* WXDivComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 77E65A0B1C155E99008B8775 /* WXDivComponent.h */; };
 		77E65A0E1C155E99008B8775 /* WXDivComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 77E65A0C1C155E99008B8775 /* WXDivComponent.m */; };
@@ -339,6 +339,13 @@
 		841CD1051F974DFA0081196D /* WXExceptionUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 841CD1041F97399C0081196D /* WXExceptionUtils.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		841CD1061F974DFA0081196D /* WXExceptionUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 841CD1041F97399C0081196D /* WXExceptionUtils.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		841CD1071F974E000081196D /* WXExceptionUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 841CD1021F9739890081196D /* WXExceptionUtils.m */; };
+		980341F323B36830000533A6 /* eagle_bridge_ext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 980341F123B3682F000533A6 /* eagle_bridge_ext.cpp */; };
+		980341F423B36830000533A6 /* eagle_bridge_ext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 980341F123B3682F000533A6 /* eagle_bridge_ext.cpp */; };
+		980341F523B36830000533A6 /* eagle_bridge_ext.h in Headers */ = {isa = PBXBuildFile; fileRef = 980341F223B36830000533A6 /* eagle_bridge_ext.h */; };
+		980341F623B36830000533A6 /* eagle_bridge_ext.h in Headers */ = {isa = PBXBuildFile; fileRef = 980341F223B36830000533A6 /* eagle_bridge_ext.h */; };
+		986CEAA723B230C2004166E0 /* WXEaglePlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 986CEAA423B230C2004166E0 /* WXEaglePlugin.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		986CEAA823B230C2004166E0 /* WXEaglePluginManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 986CEAA523B230C2004166E0 /* WXEaglePluginManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		986CEAA923B230C2004166E0 /* WXEaglePluginManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 986CEAA623B230C2004166E0 /* WXEaglePluginManager.mm */; };
 		9B9E74791FA2DB5800DAAEA9 /* WXTestBridgeMethodDummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B9E74781FA2DB5800DAAEA9 /* WXTestBridgeMethodDummy.m */; };
 		B82A159820F8556F0098A509 /* WXSDKInstance_performance.m in Sources */ = {isa = PBXBuildFile; fileRef = 17B1221F2090AA9300387E33 /* WXSDKInstance_performance.m */; };
 		B82A159920F857200098A509 /* WXSDKError.m in Sources */ = {isa = PBXBuildFile; fileRef = 17B122242090AAB000387E33 /* WXSDKError.m */; };
@@ -566,7 +573,6 @@
 		BD88C14A22F02128004467AA /* render_action_update_richtext_child_style.h in Headers */ = {isa = PBXBuildFile; fileRef = BD88C14722F02128004467AA /* render_action_update_richtext_child_style.h */; };
 		BD88C14B22F02128004467AA /* render_action_update_richtext_child_style.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD88C14822F02128004467AA /* render_action_update_richtext_child_style.cpp */; };
 		BD88C14C22F02128004467AA /* render_action_update_richtext_child_style.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD88C14822F02128004467AA /* render_action_update_richtext_child_style.cpp */; };
-		BD9205F82236518700EDF93D /* WXDataRenderHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = BD9205F72236518700EDF93D /* WXDataRenderHandler.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		BD9205FB223651D900EDF93D /* eagle_bridge.h in Headers */ = {isa = PBXBuildFile; fileRef = BD9205F9223651D800EDF93D /* eagle_bridge.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		BD9205FC223651D900EDF93D /* eagle_bridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD9205FA223651D800EDF93D /* eagle_bridge.cpp */; };
 		BDEEADBA22F2902E0099F1D7 /* time_calculator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BDEEADB822F2902D0099F1D7 /* time_calculator.cpp */; };
@@ -1206,6 +1212,11 @@
 		77E65A181C155F25008B8775 /* WXScrollerComponent.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WXScrollerComponent.mm; sourceTree = "<group>"; };
 		841CD1021F9739890081196D /* WXExceptionUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXExceptionUtils.m; sourceTree = "<group>"; };
 		841CD1041F97399C0081196D /* WXExceptionUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WXExceptionUtils.h; sourceTree = "<group>"; };
+		980341F123B3682F000533A6 /* eagle_bridge_ext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = eagle_bridge_ext.cpp; sourceTree = "<group>"; };
+		980341F223B36830000533A6 /* eagle_bridge_ext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = eagle_bridge_ext.h; sourceTree = "<group>"; };
+		986CEAA423B230C2004166E0 /* WXEaglePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXEaglePlugin.h; sourceTree = "<group>"; };
+		986CEAA523B230C2004166E0 /* WXEaglePluginManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXEaglePluginManager.h; sourceTree = "<group>"; };
+		986CEAA623B230C2004166E0 /* WXEaglePluginManager.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WXEaglePluginManager.mm; sourceTree = "<group>"; };
 		9B9E74771FA2DB5800DAAEA9 /* WXTestBridgeMethodDummy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXTestBridgeMethodDummy.h; sourceTree = "<group>"; };
 		9B9E74781FA2DB5800DAAEA9 /* WXTestBridgeMethodDummy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXTestBridgeMethodDummy.m; sourceTree = "<group>"; };
 		B8394F3521468AF100CA1EFF /* render_action_trigger_vsync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = render_action_trigger_vsync.h; sourceTree = "<group>"; };
@@ -1318,7 +1329,6 @@
 		BD88C14222F02120004467AA /* render_action_update_richtext_child_attr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = render_action_update_richtext_child_attr.cpp; sourceTree = "<group>"; };
 		BD88C14722F02128004467AA /* render_action_update_richtext_child_style.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = render_action_update_richtext_child_style.h; sourceTree = "<group>"; };
 		BD88C14822F02128004467AA /* render_action_update_richtext_child_style.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = render_action_update_richtext_child_style.cpp; sourceTree = "<group>"; };
-		BD9205F72236518700EDF93D /* WXDataRenderHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXDataRenderHandler.h; sourceTree = "<group>"; };
 		BD9205F9223651D800EDF93D /* eagle_bridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = eagle_bridge.h; sourceTree = "<group>"; };
 		BD9205FA223651D800EDF93D /* eagle_bridge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = eagle_bridge.cpp; sourceTree = "<group>"; };
 		BDEEADB822F2902D0099F1D7 /* time_calculator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = time_calculator.cpp; sourceTree = "<group>"; };
@@ -1772,6 +1782,7 @@
 		77D161181C02DCB90010B15B /* Sources */ = {
 			isa = PBXGroup;
 			children = (
+				986CEAA323B230C2004166E0 /* Plugin */,
 				17036A4B20FDE7090029AE3D /* Performance */,
 				DCA446261EFA5DAF00D0CFA8 /* WeexSDK.h */,
 				2AF626C61C191E2200E71A38 /* Layout */,
@@ -1785,7 +1796,6 @@
 				59A583031CF5B2FD0081FD3E /* Handler */,
 				77E659D71C07F585008B8775 /* Module */,
 				77D161481C02E3670010B15B /* Utility */,
-				BD9205F62236518700EDF93D /* Eagle */,
 				77D1611D1C02DDA40010B15B /* Engine */,
 				77D161191C02DD3C0010B15B /* Bridge */,
 				77D1611A1C02DD3C0010B15B /* Manager */,
@@ -2066,6 +2076,16 @@
 			path = Component;
 			sourceTree = "<group>";
 		};
+		986CEAA323B230C2004166E0 /* Plugin */ = {
+			isa = PBXGroup;
+			children = (
+				986CEAA423B230C2004166E0 /* WXEaglePlugin.h */,
+				986CEAA523B230C2004166E0 /* WXEaglePluginManager.h */,
+				986CEAA623B230C2004166E0 /* WXEaglePluginManager.mm */,
+			);
+			path = Plugin;
+			sourceTree = "<group>";
+		};
 		A5818E244F9E235722E3B938 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
@@ -2147,6 +2167,8 @@
 		B8D66B242125572F003960BD /* bridge */ = {
 			isa = PBXGroup;
 			children = (
+				980341F123B3682F000533A6 /* eagle_bridge_ext.cpp */,
+				980341F223B36830000533A6 /* eagle_bridge_ext.h */,
 				BD9205FA223651D800EDF93D /* eagle_bridge.cpp */,
 				BD9205F9223651D800EDF93D /* eagle_bridge.h */,
 				B8D66B252125572F003960BD /* platform_bridge.h */,
@@ -2382,14 +2404,6 @@
 			path = ../../../../weex_core/Source/base;
 			sourceTree = "<group>";
 		};
-		BD9205F62236518700EDF93D /* Eagle */ = {
-			isa = PBXGroup;
-			children = (
-				BD9205F72236518700EDF93D /* WXDataRenderHandler.h */,
-			);
-			path = Eagle;
-			sourceTree = "<group>";
-		};
 		C4F012711E1502A6003378D0 /* WebSocket */ = {
 			isa = PBXGroup;
 			children = (
@@ -2434,7 +2448,10 @@
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				77E659F11C0C3612008B8775 /* WXModuleFactory.h in Headers */,
 				F75C591C2313C1FC002FFF94 /* WXStreamModule.h in Headers */,
+				986CEAA723B230C2004166E0 /* WXEaglePlugin.h in Headers */,
+				986CEAA823B230C2004166E0 /* WXEaglePluginManager.h in Headers */,
 				74A4BA9E1CB3C0A100195969 /* WXHandlerFactory.h in Headers */,
 				59A583081CF5B2FD0081FD3E /* WXNavigationDefaultImpl.h in Headers */,
 				2A837AB61CD9DE9200AEDF03 /* WXRefreshComponent.h in Headers */,
@@ -2606,7 +2623,6 @@
 				B8D66C2921255730003960BD /* render_page.h in Headers */,
 				DCC77C141D770AE300CE7288 /* WXSliderNeighborComponent.h in Headers */,
 				747DF6821E31AEE4005C53A8 /* WXLength.h in Headers */,
-				77E659F11C0C3612008B8775 /* WXModuleFactory.h in Headers */,
 				77D161431C02DEE40010B15B /* WXBridgeProtocol.h in Headers */,
 				B8D66C1721255730003960BD /* script_bridge.h in Headers */,
 				59A582D41CF481110081FD3E /* WXAppMonitorProtocol.h in Headers */,
@@ -2653,6 +2669,7 @@
 				744D610C1E49978200B624B3 /* WXHeaderComponent.h in Headers */,
 				B8D66C1521255730003960BD /* wx_type_define.h in Headers */,
 				B8D66C7921255730003960BD /* render_list.h in Headers */,
+				980341F523B36830000533A6 /* eagle_bridge_ext.h in Headers */,
 				B8D66C3321255730003960BD /* render_action_update_attr.h in Headers */,
 				77D1613C1C02DEA60010B15B /* WXJSCoreBridge.h in Headers */,
 				74D205201E091B8000128F44 /* WXCallJSMethod.h in Headers */,
@@ -2903,6 +2920,7 @@
 				B8D66C1021255730003960BD /* core_side_in_platform.h in Headers */,
 				DCA445D41EFA594E00D0CFA8 /* UIBezierPath+Weex.h in Headers */,
 				DCA446031EFA5A5200D0CFA8 /* WXCanvasModule.h in Headers */,
+				980341F623B36830000533A6 /* eagle_bridge_ext.h in Headers */,
 				B8D66C4221255730003960BD /* render_action_add_event.h in Headers */,
 				DCA445EF1EFA5A1800D0CFA8 /* WXSwitchComponent.h in Headers */,
 				B8D66CB421255730003960BD /* make_copyable.h in Headers */,
@@ -3211,10 +3229,12 @@
 				33CE19102153443000CF9670 /* WXJSFrameworkLoadDefaultImpl.m in Sources */,
 				B8D66C7321255730003960BD /* render_list.cpp in Sources */,
 				740451EB1E14BB26004157CB /* WXServiceFactory.m in Sources */,
+				980341F323B36830000533A6 /* eagle_bridge_ext.cpp in Sources */,
 				B8D66C6521255730003960BD /* render_mask.cpp in Sources */,
 				77E659DB1C07F594008B8775 /* WXDomModule.m in Sources */,
 				D3FC0DF81C508B2A002B9E31 /* WXTimerModule.m in Sources */,
 				594C28921CF9E61A009793A4 /* WXAnimationModule.m in Sources */,
+				986CEAA923B230C2004166E0 /* WXEaglePluginManager.mm in Sources */,
 				B8D66C6F21255730003960BD /* render_object.cpp in Sources */,
 				BD88C13D22F02111004467AA /* render_action_remove_child_from_richtext.cpp in Sources */,
 				59A5961D1CB630F10012CD52 /* WXComponent+Navigation.m in Sources */,
@@ -3424,6 +3444,7 @@
 				DCA445491EFA55B300D0CFA8 /* WXRefreshComponent.mm in Sources */,
 				B8D66CA021255730003960BD /* json11.cc in Sources */,
 				DCA4454A1EFA55B300D0CFA8 /* WXEmbedComponent.m in Sources */,
+				980341F423B36830000533A6 /* eagle_bridge_ext.cpp in Sources */,
 				74B81AE81F73C3E900D3A61D /* WXRecycleListTemplateManager.m in Sources */,
 				DCA4454B1EFA55B300D0CFA8 /* WXVideoComponent.m in Sources */,
 				74B81AE61F73C3E900D3A61D /* WXRecycleListDataManager.m in Sources */,
@@ -3576,6 +3597,7 @@
 				OTHER_LDFLAGS = "-ObjC";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SKIP_INSTALL = YES;
+				VALID_ARCHS = "$(ARCHS_STANDARD)";
 			};
 			name = Debug;
 		};
@@ -3588,6 +3610,7 @@
 				OTHER_LDFLAGS = "-ObjC";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SKIP_INSTALL = YES;
+				VALID_ARCHS = "$(ARCHS_STANDARD)";
 			};
 			name = Release;
 		};
@@ -3820,7 +3843,7 @@
 				PROVISIONING_PROFILE_SPECIFIER = "";
 				"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "";
 				SKIP_INSTALL = YES;
-				VALID_ARCHS = "arm64 armv7 x86_64 i386";
+				VALID_ARCHS = "$(ARCHS_STANDARD)";
 				WARNING_CFLAGS = "";
 			};
 			name = Debug;
@@ -3879,7 +3902,7 @@
 				PROVISIONING_PROFILE_SPECIFIER = "";
 				"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "";
 				SKIP_INSTALL = YES;
-				VALID_ARCHS = "arm64 armv7 x86_64 i386";
+				VALID_ARCHS = "$(ARCHS_STANDARD)";
 				WARNING_CFLAGS = "";
 			};
 			name = Release;
@@ -3927,6 +3950,7 @@
 				PRODUCT_BUNDLE_IDENTIFIER = "com.taobao.WeexSDK-Dynamic";
 				PRODUCT_NAME = WeexSDK;
 				SKIP_INSTALL = YES;
+				VALID_ARCHS = "$(ARCHS_STANDARD)";
 				WARNING_CFLAGS = "-Wno-documentation";
 			};
 			name = Debug;
@@ -3974,6 +3998,7 @@
 				PRODUCT_BUNDLE_IDENTIFIER = "com.taobao.WeexSDK-Dynamic";
 				PRODUCT_NAME = WeexSDK;
 				SKIP_INSTALL = YES;
+				VALID_ARCHS = "$(ARCHS_STANDARD)";
 				WARNING_CFLAGS = "-Wno-documentation";
 			};
 			name = Release;
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
index 7f1e8f1..1df0948 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
@@ -51,7 +51,7 @@
 #import "WXJSFrameworkLoadDefaultImpl.h"
 #import "WXHandlerFactory.h"
 #import "WXExtendCallNativeManager.h"
-#import "WXDataRenderHandler.h"
+#import "WXEaglePluginManager.h"
 
 #define SuppressPerformSelectorLeakWarning(Stuff) \
 do { \
@@ -77,14 +77,10 @@ _Pragma("clang diagnostic pop") \
 // store service
 @property (nonatomic, strong) NSMutableArray *jsServiceQueue;
 
-@property (nonatomic, readonly) id<WXDataRenderHandler> dataRenderHandler;
-
 @end
 
 @implementation WXBridgeContext
     
-@synthesize dataRenderHandler = _dataRenderHandler;
-
 - (instancetype) init
 {
     self = [super init];
@@ -92,14 +88,6 @@ _Pragma("clang diagnostic pop") \
         _methodQueue = [NSMutableArray new];
         _frameworkLoadFinished = NO;
         _jsServiceQueue = [NSMutableArray new];
-        _dataRenderHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXDataRenderHandler)];
-        if (!_dataRenderHandler) {
-            Class handlerClass = NSClassFromString(@"WXEagleHandler");
-            if (handlerClass) {
-                _dataRenderHandler = [[handlerClass alloc] init];
-                [WXSDKEngine registerHandler:_dataRenderHandler withProtocol:@protocol(WXDataRenderHandler)];
-            }
-        }
     }
     return self;
 }
@@ -145,12 +133,13 @@ _Pragma("clang diagnostic pop") \
     }];
     
     [_jsBridge registerCallUpdateComponentData:^NSInteger(NSString *instanceId, NSString *componentId, NSString *jsonData) {
-        if (weakSelf.dataRenderHandler) {
+        WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId];
+        if (instance.renderPlugin) {
             WXPerformBlockOnComponentThread(^{
                 long start = [WXUtility getUnixFixTimeMillis];
                 WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId];
                 [instance.apmInstance addUpdateComponentDataTimestamp:start];
-                [weakSelf.dataRenderHandler callUpdateComponentData:instanceId componentId:componentId jsonData:jsonData];
+                [instance.renderPlugin updateInstance:instanceId component:componentId jsonData:jsonData];
                 [instance.apmInstance addUpdateComponentDataTime:[WXUtility getUnixFixTimeMillis] - start];
             });
         }
@@ -490,10 +479,10 @@ _Pragma("clang diagnostic pop") \
     NSMutableArray *sendQueue = [NSMutableArray array];
     [self.sendQueue setValue:sendQueue forKey:instanceIdString];
 
-    if (sdkInstance.dataRender && ![options[@"EXEC_JS"] boolValue]) {
-        if (_dataRenderHandler) {
+    if (sdkInstance.renderPlugin && ![options[@"EXEC_JS"] boolValue]) {
+        if (sdkInstance.renderPlugin) {
             WXPerformBlockOnComponentThread(^{
-                [_dataRenderHandler createPage:instanceIdString template:jsBundleString options:options data:data];
+                [sdkInstance.renderPlugin createPage:instanceIdString contents:jsBundleString options:options data:data];
             });
         }
         else {
@@ -666,23 +655,19 @@ _Pragma("clang diagnostic pop") \
     NSMutableArray *sendQueue = [NSMutableArray array];
     [self.sendQueue setValue:sendQueue forKey:instanceIdString];
 
-    if (sdkInstance.dataRender) {
-        if (_dataRenderHandler) {
+    if (sdkInstance.renderPlugin) {
+        WXPerformBlockOnComponentThread(^{
+            [sdkInstance.renderPlugin createPage:instanceIdString contents:contents options:options data:data];
+        });
+    } else {
+        WXComponentManager *manager = sdkInstance.componentManager;
+        if (manager.isValid) {
+            WXSDKErrCode errorCode = WX_KEY_EXCEPTION_DEGRADE_EAGLE_RENDER_ERROR;
+            NSError *error = [NSError errorWithDomain:WX_ERROR_DOMAIN code:errorCode userInfo:@{@"message":@"No data render handler found!"}];
             WXPerformBlockOnComponentThread(^{
-                [_dataRenderHandler createPage:instanceIdString contents:contents options:options data:data];
+                [manager renderFailed:error];
             });
         }
-        else {
-            WXComponentManager *manager = sdkInstance.componentManager;
-            if (manager.isValid) {
-                WXSDKErrCode errorCode = WX_KEY_EXCEPTION_DEGRADE_EAGLE_RENDER_ERROR;
-                NSError *error = [NSError errorWithDomain:WX_ERROR_DOMAIN code:errorCode userInfo:@{@"message":@"No data render handler found!"}];
-                WXPerformBlockOnComponentThread(^{
-                    [manager renderFailed:error];
-                });
-            }
-        }
-        return;
     }
 }
 
@@ -799,7 +784,7 @@ _Pragma("clang diagnostic pop") \
     }
     
     WXSDKInstance *sdkInstance = [WXSDKManager instanceForID:instance];
-    if (!sdkInstance.wlasmRender) {
+    if (!sdkInstance.renderPlugin || sdkInstance.renderPlugin.isSupportExecScript) {
         [self callJSMethod:@"destroyInstance" args:@[instance]];
     }
 }
@@ -820,24 +805,9 @@ _Pragma("clang diagnostic pop") \
     if (!data) return;
     
     WXSDKInstance *sdkInstance = [WXSDKManager instanceForID:instance];
-    if (sdkInstance.dataRender) {
-        if (!_dataRenderHandler) {
-            WXComponentManager *manager = sdkInstance.componentManager;
-            if (manager.isValid) {
-                WXSDKErrCode errorCode = WX_KEY_EXCEPTION_DEGRADE_EAGLE_RENDER_ERROR;
-                NSError *error = [NSError errorWithDomain:WX_ERROR_DOMAIN code:errorCode userInfo:@{@"message":@"No data render handler found!"}];
-                WXPerformBlockOnComponentThread(^{
-                    [manager renderFailed:error];
-                });
-            }
-            return;
-        }
+    if (sdkInstance.renderPlugin) {
         WXPerformBlockOnComponentThread(^{
-            if ([data isKindOfClass:[NSDictionary class]]) {
-                [_dataRenderHandler refreshDataRenderInstance:instance data:[WXUtility JSONString:data]];
-            } else if ([data isKindOfClass:[NSString class]]) {
-                [_dataRenderHandler refreshDataRenderInstance:instance data:data];
-            }
+            [sdkInstance.renderPlugin refreshInstance:instance data:[WXUtility JSONString:data]];
         });
         [[WXSDKManager bridgeMgr] callJSMethod:@"callJS" args:@[instance, @[@{@"method":@"fireEvent", @"args":@[@"", @"refresh", [WXUtility objectFromJSON:@"[]"], @"", @{@"params":@[@{@"data":data}]}]}]]];
     } else {
@@ -995,11 +965,7 @@ _Pragma("clang diagnostic pop") \
     if(!modules) return;
     
     [self callJSMethod:@"registerModules" args:@[modules]];
-    if (_dataRenderHandler) {
-        WXPerformBlockOnComponentThread(^{
-            [_dataRenderHandler registerModules:modules];
-        });
-    }
+    [WXEaglePluginManager registerModules:modules];
 }
 
 - (void)registerComponents:(NSArray *)components
@@ -1009,11 +975,7 @@ _Pragma("clang diagnostic pop") \
     if(!components) return;
     
     [self callJSMethod:@"registerComponents" args:@[components]];
-    if (_dataRenderHandler) {
-        WXPerformBlockOnComponentThread(^{
-            [_dataRenderHandler registerComponents:components];
-        });
-    }
+    [WXEaglePluginManager registerComponents:components];
 }
 
 - (void)callJSMethod:(NSString *)method args:(NSArray *)args
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
index 4f6a3f2..c5106a2 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
@@ -34,7 +34,6 @@
 #import "WXThreadSafeMutableArray.h"
 #import "WXComponentManager.h"
 #import "WXCoreBridge.h"
-#import "WXDataRenderHandler.h"
 #import "WXHandlerFactory.h"
 #import "WXUtility.h"
 #import "WXExceptionUtils.h"
@@ -632,23 +631,10 @@ void WXPerformBlockSyncOnBridgeThreadForInstance(void (^block) (void), NSString*
 - (void)fireEvent:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params domChanges:(NSDictionary *)domChanges handlerArguments:(NSArray *)handlerArguments
 {
     WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId];
-    if (instance.dataRender) {
-        id<WXDataRenderHandler> dataRenderHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXDataRenderHandler)];
-        if (dataRenderHandler) {
-            WXPerformBlockOnComponentThread(^{
-                [dataRenderHandler fireEvent:instanceId ref:ref event:type args:params?:@{} domChanges:domChanges?:@{}];
-            });
-        }
-        else {
-            WXComponentManager *manager = instance.componentManager;
-            if (manager.isValid) {
-                WXSDKErrCode errorCode = WX_KEY_EXCEPTION_DEGRADE_EAGLE_RENDER_ERROR;
-                NSError *error = [NSError errorWithDomain:WX_ERROR_DOMAIN code:errorCode userInfo:@{@"message":@"No data render handler found!"}];
-                WXPerformBlockOnComponentThread(^{
-                    [manager renderFailed:error];
-                });
-            }
-        }
+    if (instance.renderPlugin.isSupportFireEvent) {
+        WXPerformBlockOnComponentThread(^{
+            [instance.renderPlugin fireEvent:instanceId ref:ref event:type args:params?:@{} domChanges:domChanges?:@{}];
+        });
         return;
     }
 
@@ -714,24 +700,11 @@ void WXPerformBlockSyncOnBridgeThreadForInstance(void (^block) (void), NSString*
         args = @[[funcId copy], params? [params copy]:@"\"{}\""];
     }
     WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId];
-    if (instance.wlasmRender) {
-        id<WXDataRenderHandler> dataRenderHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXDataRenderHandler)];
-        if (dataRenderHandler) {
-            id strongArgs = params ? [params copy]:@"\"{}\"";
-            WXPerformBlockOnComponentThread(^{
-                [dataRenderHandler invokeCallBack:instanceId function:funcId args:strongArgs keepAlive:keepAlive];
-            });
-        }
-        else {
-            WXComponentManager *manager = instance.componentManager;
-            if (manager.isValid) {
-                WXSDKErrCode errorCode = WX_KEY_EXCEPTION_DEGRADE_EAGLE_RENDER_ERROR;
-                NSError *error = [NSError errorWithDomain:WX_ERROR_DOMAIN code:errorCode userInfo:@{@"message":@"No data render handler found!"}];
-                WXPerformBlockOnComponentThread(^{
-                    [manager renderFailed:error];
-                });
-            }
-        }
+    if (instance.renderPlugin.isSupportInvokeJSCallBack) {
+        id strongArgs = params ? [params copy]:@"\"{}\"";
+        WXPerformBlockOnComponentThread(^{
+            [instance.renderPlugin invokeCallBack:instanceId function:funcId args:strongArgs keepAlive:keepAlive];
+        });
     }
     else {
         WXCallJSMethod *method = [[WXCallJSMethod alloc] initWithModuleName:@"jsBridge" methodName:@"callback" arguments:args instance:instance];
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm
index 0a86a77..9f89fcb 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm
@@ -942,7 +942,7 @@ static NSThread *WXComponentThread;
     [self _addUITask:^{
         UIView *rootView = instance.rootView;
         [instance.performance onInstanceRenderSuccess:instance];
-        if (instance.wlasmRender) {
+        if ([instance.renderPlugin.pluginName isEqualToString:@"EagleRax"]) {
             [instance.apmInstance forceSetInteractionTime:[WXUtility getUnixFixTimeMillis]];
         }
         if (instance.renderFinish) {
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h
index 84e6802..5cd5de6 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h
+++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h
@@ -197,16 +197,6 @@ typedef enum : NSUInteger {
  * bundleType is the DSL type
  */
 @property (nonatomic, strong) NSString * bundleType;
-
-/**
- *  Which decide whether to use data render,default value is false
- */
-@property (nonatomic, assign, readonly) BOOL dataRender;
-
-/**
- *  Which decide whether to use binary code render, default value is false
- */
-@property (nonatomic, assign, readonly) BOOL wlasmRender;
     
 /**
  *  The callback triggered when the instance fails to render.
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
index 67d2233..cdfd2b3 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
@@ -51,11 +51,10 @@
 #import "WXPageEventNotifyEvent.h"
 #import "WXConvertUtility.h"
 #import "WXCoreBridge.h"
-#import "WXDataRenderHandler.h"
 #import "WXDarkSchemeProtocol.h"
 #import "WXDarkSchemeModule.h"
+#import <WeexSDK/WXEaglePluginManager.h>
 
-#define WEEX_LITE_URL_SUFFIX           @"wlasm"
 #define WEEX_RENDER_TYPE_PLATFORM       @"platform"
 
 NSString *const bundleUrlOptionKey = @"bundleUrl";
@@ -86,7 +85,6 @@ typedef enum : NSUInteger {
     BOOL _performanceCommit;
     BOOL _debugJS;
     id<WXBridgeProtocol> _instanceJavaScriptContext; // sandbox javaScript context
-    BOOL _defaultDataRender;
     NSMutableDictionary *_moduleIntercepts;
 }
 
@@ -164,9 +162,7 @@ typedef enum : NSUInteger {
         
         _performance = [[WXPerformance alloc] init];
         _apmInstance = [[WXApmForInstance alloc] init];
-        
-        _defaultDataRender = NO;
-        
+                
         _useBackupJsThread = NO;
 
         [self addObservers];
@@ -339,12 +335,16 @@ typedef enum : NSUInteger {
     }
     WXLogInfo(@"pageid: %@ renderWithURL: %@", _instanceId, url.absoluteString);
     
+    _renderPlugin = [WXEaglePluginManager renderWithURL:&url];
+    if (!_renderPlugin) {
+        _renderPlugin = [WXEaglePluginManager renderWithOption:options];
+    }
     @synchronized (lastPageInfoLock) {
         lastPageInfo = @{@"pageId": [_instanceId copy], @"url": [url absoluteString] ?: @""};
     }
     
     [WXCoreBridge install];
-    if (_useBackupJsThread) {
+    if (_useBackupJsThread && !self.renderPlugin.isSkipFramework) {
         [[WXSDKManager bridgeMgr] executeJSTaskQueue];
     }
 
@@ -357,14 +357,19 @@ typedef enum : NSUInteger {
     WXResourceRequest *request = [WXResourceRequest requestWithURL:url resourceType:WXResourceTypeMainBundle referrer:@"" cachePolicy:NSURLRequestUseProtocolCachePolicy];
     [self _renderWithRequest:request options:options data:data];
 
-    NSURL* nsURL = [NSURL URLWithString:options[@"DATA_RENDER_JS"]];
-    [self _downloadAndExecScript:nsURL];
+    if (self.renderPlugin.isSupportExecScript) {
+        NSMutableDictionary *newOptions = [NSMutableDictionary dictionaryWithDictionary:options];
+        [newOptions setValue:_jsData forKey:@"jsData"];
+        [self.renderPlugin runPluginTask:_instanceId task:@"_downloadAndExecScript:options:" options:newOptions];
+    }
 }
 
 - (void)renderView:(id)source options:(NSDictionary *)options data:(id)data
 {
     _options = [options isKindOfClass:[NSDictionary class]] ? options : nil;
     _jsData = data;
+    _renderPlugin = [WXEaglePluginManager renderWithOption:_options];
+    
     WXLogInfo(@"pageid: %@ renderView pageNmae: %@  options: %@", _instanceId, _pageName, options);
     
     @synchronized (lastPageInfoLock) {
@@ -372,7 +377,7 @@ typedef enum : NSUInteger {
     }
 
     [WXCoreBridge install];
-    if (_useBackupJsThread) {
+    if (_useBackupJsThread && !self.renderPlugin.isSkipFramework) {
         [[WXSDKManager bridgeMgr] executeJSTaskQueue];
     }
 
@@ -384,37 +389,12 @@ typedef enum : NSUInteger {
     } else if ([source isKindOfClass:[NSData class]]) {
         [self _renderWithData:source];
     }
-    NSURL* nsURL = [NSURL URLWithString:options[@"DATA_RENDER_JS"]];
-    [self _downloadAndExecScript:nsURL];
-}
-
-- (void)_downloadAndExecScript:(NSURL *)url {
-    [[WXSDKManager bridgeMgr] DownloadJS:_instanceId url:url completion:^(NSString *script) {
-        if (!script) {
-            return;
-        }
-        if (self.dataRender) {
-            id<WXDataRenderHandler> dataRenderHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXDataRenderHandler)];
-            if (dataRenderHandler) {
-                [[WXSDKManager bridgeMgr] createInstanceForJS:_instanceId template:script options:_options data:_jsData];
-
-                NSString* instanceId = self.instanceId;
-                WXPerformBlockOnComponentThread(^{
-                    [dataRenderHandler DispatchPageLifecycle:instanceId];
-                });
-            }
-            else {
-                if (self.componentManager.isValid) {
-                    WXSDKErrCode errorCode = WX_KEY_EXCEPTION_DEGRADE_EAGLE_RENDER_ERROR;
-                    NSError *error = [NSError errorWithDomain:WX_ERROR_DOMAIN code:errorCode userInfo:@{@"message":@"No data render handler found!"}];
-                    WXPerformBlockOnComponentThread(^{
-                        [self.componentManager renderFailed:error];
-                    });
-                }
-            }
-            return;
-        }
-    }];
+    
+    if (self.renderPlugin.isSupportExecScript) {
+        NSMutableDictionary *newOptions = [NSMutableDictionary dictionaryWithDictionary:options];
+        [newOptions setValue:_jsData forKey:@"jsData"];
+        [self.renderPlugin runPluginTask:_instanceId task:@"_downloadAndExecScript:options:" options:newOptions];
+    }
 }
 
 - (NSString *) bundleTemplate
@@ -439,7 +419,7 @@ typedef enum : NSUInteger {
     self.apmInstance.isStartRender = YES;
     
     [_apmInstance setProperty:KEY_PAGE_PROPERTIES_UIKIT_TYPE withValue:_renderType?: WEEX_RENDER_TYPE_PLATFORM];
-    if (self.dataRender) {
+    if (self.renderPlugin) {
         [self.apmInstance setProperty:KEY_PAGE_PROPERTIES_RENDER_TYPE withValue:@"eagle"];
     }
 
@@ -532,7 +512,7 @@ typedef enum : NSUInteger {
     self.apmInstance.isStartRender = YES;
     
     [_apmInstance setProperty:KEY_PAGE_PROPERTIES_UIKIT_TYPE withValue:_renderType?: WEEX_RENDER_TYPE_PLATFORM];
-    if (self.dataRender) {
+    if (self.renderPlugin) {
         [self.apmInstance setProperty:KEY_PAGE_PROPERTIES_RENDER_TYPE withValue:@"eagle"];
     }
     
@@ -665,14 +645,6 @@ typedef enum : NSUInteger {
         newOptions[bundleUrlOptionKey] = url.absoluteString;
     }
 
-    if ( [url.absoluteString containsString:@"__data_render=true"]) {
-        newOptions[@"DATA_RENDER"] = @(YES);
-    }
-
-    if ([url.absoluteString hasSuffix:WEEX_LITE_URL_SUFFIX] || [url.absoluteString containsString:@"__eagle=true"]) {
-        newOptions[@"WLASM_RENDER"] = @(YES);
-    }
-
     // compatible with some wrong type, remove this hopefully in the future.
     if ([newOptions[bundleUrlOptionKey] isKindOfClass:[NSURL class]]) {
         WXLogWarning(@"Error type in options with key:bundleUrl, should be of type NSString, not NSURL!");
@@ -738,7 +710,7 @@ typedef enum : NSUInteger {
             return;
         }
         
-        if (([newOptions[@"DATA_RENDER"] boolValue] && [newOptions[@"RENDER_WITH_BINARY"] boolValue]) || [newOptions[@"WLASM_RENDER"] boolValue]) {
+        if (strongSelf.renderPlugin) {
             [strongSelf.apmInstance onStage:KEY_PAGE_STAGES_DOWN_BUNDLE_END];
             [strongSelf _renderWithData:data];
             return;
@@ -853,9 +825,7 @@ typedef enum : NSUInteger {
 
     [WXPrerenderManager removePrerenderTaskforUrl:[self.scriptURL absoluteString]];
     [WXPrerenderManager destroyTask:self.instanceId];
-    BOOL dataRender = self.dataRender;
-    BOOL wlasmRender = self.wlasmRender;
-    if (!dataRender) {
+    if (!self.renderPlugin) {
         [[WXSDKManager bridgeMgr] destroyInstance:self.instanceId];
     }
     
@@ -875,7 +845,7 @@ typedef enum : NSUInteger {
         // Destroy weexcore c++ page and objects.
         [WXCoreBridge closePage:instanceId];
         
-        if (dataRender && !wlasmRender) {
+        if (self.renderPlugin.isSupportExecScript) {
             [[WXSDKManager bridgeMgr] destroyInstance:instanceId];
         }
 
@@ -991,21 +961,6 @@ typedef enum : NSUInteger {
     return usingScreenWidth / usingViewPort;
 }
     
-- (BOOL)wlasmRender {
-    if ([_options[@"WLASM_RENDER"] boolValue] || [_scriptURL.pathExtension isEqualToString:@"wlasm"] || [_scriptURL.pathExtension isEqualToString:@"wlm"]) {
-        return YES;
-    }
-    return NO;
-}
-
-- (BOOL)dataRender
-{
-    if ([_options[@"DATA_RENDER"] boolValue] || [_options[@"WLASM_RENDER"] boolValue]) {
-        return YES;
-    }
-    return _defaultDataRender;
-}
-
 - (NSURL *)completeURL:(NSString *)url
 {
     if (!_scriptURL) {
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h
index 30cd209..38e5bb2 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h
+++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h
@@ -22,6 +22,7 @@
 #import "WXModuleMethod.h"
 #import "WXThreadSafeMutableDictionary.h"
 #import <JavaScriptCore/JavaScriptCore.h>
+#import <WeexSDK/WXEaglePlugin.h>
 
 @interface WXSDKInstance ()
 
@@ -33,6 +34,7 @@
 @property (nonatomic, strong) NSMutableDictionary *styleConfigs;
 @property (nonatomic, strong) NSMutableDictionary *attrConfigs;
 @property (nonatomic, strong) NSString *mainBundleString;
+@property (nonatomic, weak) id <WXEaglePlugin> renderPlugin;
 
 // add monitor information
 @property (nonatomic, strong) NSString *callCreateInstanceContext;
diff --git a/ios/sdk/WeexSDK/Sources/Eagle/WXDataRenderHandler.h b/ios/sdk/WeexSDK/Sources/Plugin/WXEaglePlugin.h
similarity index 55%
rename from ios/sdk/WeexSDK/Sources/Eagle/WXDataRenderHandler.h
rename to ios/sdk/WeexSDK/Sources/Plugin/WXEaglePlugin.h
index b54b401..5b0d35b 100644
--- a/ios/sdk/WeexSDK/Sources/Eagle/WXDataRenderHandler.h
+++ b/ios/sdk/WeexSDK/Sources/Plugin/WXEaglePlugin.h
@@ -21,17 +21,30 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
-@protocol WXDataRenderHandler <NSObject>
-    
-- (void)createPage:(NSString *)pageId template:(NSString *)jsBundleString options:(NSDictionary * _Nullable)options  data:(id)data;
+@protocol WXEaglePlugin <NSObject>
+
+@required
+
+@property (nonatomic, readonly) NSString* pluginName;
+@property (nonatomic, readonly) BOOL isSkipFramework;
+@property (nonatomic, readonly) BOOL isSupportInvokeJSCallBack;
+@property (nonatomic, readonly) BOOL isSupportExecScript;
+@property (nonatomic, readonly) BOOL isSupportFireEvent;
+@property (nonatomic, readonly) BOOL isRegisterModules;
+@property (nonatomic, readonly) BOOL isRegisterComponents;
+@property (nonatomic, readonly) NSDictionary *options;
 
-- (void)createPage:(NSString *)pageId contents:(NSData *)contents options:(NSDictionary * _Nullable)options data:(id)data;
+- (BOOL)renderWithOption:(NSDictionary *)option;
 
-- (void)callUpdateComponentData:(NSString*)pageId componentId:(NSString*)componentId jsonData:(NSString*)jsonData;
+- (NSURL *)renderWithURL:(NSURL *)url;
 
-- (void)destroyDataRenderInstance:(NSString *)pageId;
+- (void)refreshInstance:(NSString *)pageId data:(id)data;
 
-- (void)refreshDataRenderInstance:(NSString *)pageId data:(NSString *)data;
+- (void)createPage:(NSString *)pageId contents:(id)contents options:(NSDictionary * _Nullable)options data:(id)data;
+
+- (BOOL)runPluginTask:(NSString *)pageId task:(NSString *)task options:(id)options;
+
+@optional
 
 - (void)fireEvent:(NSString *)pageId ref:(NSString *)ref event:(NSString *)event args:(NSDictionary * _Nullable)args domChanges:(NSDictionary * _Nullable)domChanges;
 
@@ -39,10 +52,12 @@ NS_ASSUME_NONNULL_BEGIN
     
 - (void)registerComponents:(NSArray *)components;
     
-- (void)invokeCallBack:(NSString *)pageId function:(NSString *)funcId args:(NSDictionary * _Nullable)args keepAlive:(BOOL)keepAlive;
+- (void)invokeCallBack:(NSString *)pageId function:(NSString *)functionId args:(NSDictionary * _Nullable)args keepAlive:(BOOL)keepAlive;
 
 - (void)DispatchPageLifecycle:(NSString *)pageId;
 
+- (void)updateInstance:(NSString *)pageId component:(NSString *)componentId jsonData:(id)jsonData;
+
 @end
 
 NS_ASSUME_NONNULL_END
diff --git a/ios/sdk/WeexSDK/Sources/Plugin/WXEaglePluginManager.h b/ios/sdk/WeexSDK/Sources/Plugin/WXEaglePluginManager.h
new file mode 100644
index 0000000..3b73f96
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Plugin/WXEaglePluginManager.h
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef WX_EAGLE_PLUGIN_MACRO_H
+#define WX_EAGLE_PLUGIN_MACRO_H
+
+#import <Foundation/Foundation.h>
+#import <WeexSDK/WXEaglePlugin.h>
+
+#define WX_EAGLE_PLUGIN_DATA  __attribute((used, section("__DATA, WXEaglePlugin")))
+
+#define WX_EAGLE_PLUGIN_NAME_SEPARATOR(plugin, class, separator) #plugin#separator#class
+
+#define WX_EAGLE_PLUGIN_NAME(plugin, class)  WX_EAGLE_PLUGIN_NAME_SEPARATOR(plugin, class, &)
+
+#define WX_EAGLE_PlUGIN_EXPORT(plugin, class)  \
+char const* k##class##Configuration WX_EAGLE_PLUGIN_DATA = WX_EAGLE_PLUGIN_NAME(plugin, class);
+
+@interface WXEaglePluginManager : NSObject
+
+/**
+ * @abstract Returns the render handler for render option
+ *
+ **/
++ (id<WXEaglePlugin>)renderWithOption:(NSDictionary *)option;
+
++ (id<WXEaglePlugin>)renderWithURL:(NSURL **)url;
+
++ (void)registerModules:(NSDictionary *)modules;
+
++ (void)registerComponents:(NSArray *)components;
+
+@end
+
+#endif // WX_EAGLE_PLUGIN_MACRO_H
diff --git a/ios/sdk/WeexSDK/Sources/Plugin/WXEaglePluginManager.mm b/ios/sdk/WeexSDK/Sources/Plugin/WXEaglePluginManager.mm
new file mode 100644
index 0000000..abb24e8
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Plugin/WXEaglePluginManager.mm
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <mach-o/getsect.h>
+#include <mach-o/loader.h>
+#include <mach-o/dyld.h>
+#include <dlfcn.h>
+#import "WXEaglePluginManager.h"
+#import "WXThreadSafeMutableDictionary.h"
+#import "WXComponentManager.h"
+
+#define WX_EAGLE_PLUGIN_SECTION_NAME   "WXEaglePlugin"
+
+static NSArray<NSString *>* pluginConfigs() {
+    static NSMutableArray *configs;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        Dl_info info;
+        dladdr((const void *)pluginConfigs, &info);
+#ifndef __LP64__
+        //        const struct mach_header *mhp = _dyld_get_image_header(0); // both works as below line
+        const struct mach_header *mhp = (struct mach_header *)info.dli_fbase;
+        unsigned long size = 0;
+        uint32_t *memory = (uint32_t *)getsectiondata(mhp, "__DATA", WX_EAGLE_PLUGIN_SECTION_NAME, &size);
+#else /* defined(__LP64__) */
+        const struct mach_header_64 *mhp = (struct mach_header_64*)info.dli_fbase;
+        unsigned long size = 0;
+        uint64_t *memory = (uint64_t*)getsectiondata(mhp, "__DATA", WX_EAGLE_PLUGIN_SECTION_NAME, &size);
+#endif /* defined(__LP64__) */
+        configs = [NSMutableArray new];
+        for(int idx = 0; idx < size / sizeof(void *); ++idx) {
+            char *string = (char *)memory[idx];
+            NSString *str = [NSString stringWithUTF8String:string];
+            if (str && [str length] > 0) {
+                [configs addObject:str];
+            }
+        }
+    });
+    return configs;
+}
+
+@interface WXEaglePluginManager ()
+
+@property (nonatomic, strong) WXThreadSafeMutableDictionary *plugins;
+
+- (void)registerModules:(NSDictionary *)modules;
+- (void)registerComponents:(NSArray *)components;
+- (id<WXEaglePlugin>)renderWithOption:(NSDictionary *)option;
+- (id<WXEaglePlugin>)renderWithURL:(NSURL **)url;
+
+@end
+
+@implementation WXEaglePluginManager
+
+- (instancetype)init {
+    if (self = [super init]) {
+        self.plugins = [[WXThreadSafeMutableDictionary alloc] init];
+        [self registerWXPlugins];
+    }
+    return self;
+}
+
++ (instancetype)sharedInstance {
+    static WXEaglePluginManager* instance = nil;
+    static dispatch_once_t oncePredicate;
+    dispatch_once(&oncePredicate, ^{
+        instance = [[self alloc] init];
+    });
+    return instance;
+}
+
++ (id<WXEaglePlugin>)renderWithOption:(NSDictionary *)option {
+    WXEaglePluginManager *manager = [WXEaglePluginManager sharedInstance];
+    return [manager renderWithOption:option];
+}
+
+
++ (id<WXEaglePlugin>)renderWithURL:(NSURL **)url {
+    WXEaglePluginManager *manager = [WXEaglePluginManager sharedInstance];
+    return [manager renderWithURL:url];
+}
+
+
++ (void)registerModules:(NSDictionary *)modules {
+    WXEaglePluginManager *manager = [WXEaglePluginManager sharedInstance];
+    [manager registerModules:modules];
+}
+
++ (void)registerComponents:(NSArray *)components {
+    WXEaglePluginManager *manager = [WXEaglePluginManager sharedInstance];
+    [manager registerComponents:components];
+}
+
+- (void)registerModules:(NSDictionary *)modules {
+    NSArray *plugins = [self.plugins allValues];
+    for (id<WXEaglePlugin>plugin in plugins) {
+        if (plugin.isRegisterModules) {
+            WXPerformBlockOnComponentThread(^{
+                [plugin registerModules:modules];
+            });
+        }
+    }
+}
+
+- (void)registerComponents:(NSArray *)components {
+    NSArray *plugins = [self.plugins allValues];
+    for (id<WXEaglePlugin>plugin in plugins) {
+        if (plugin.isRegisterComponents) {
+            WXPerformBlockOnComponentThread(^{
+                [plugin registerComponents:components];
+            });
+        }
+    }
+}
+
+- (id<WXEaglePlugin>)renderWithOption:(NSDictionary *)option {
+    NSArray *plugins = [self.plugins allValues];
+    for (id<WXEaglePlugin>plugin in plugins) {
+        if ([plugin renderWithOption:option]) {
+            return plugin;
+        }
+    }
+    return nil;
+}
+
+- (id<WXEaglePlugin>)renderWithURL:(NSURL **)url {
+    NSArray *plugins = [self.plugins allValues];
+    for (id<WXEaglePlugin>plugin in plugins) {
+        NSURL *newURL = [plugin renderWithURL:*url];
+        if (newURL) {
+            if (url) {
+                *url = newURL;
+            }
+            return plugin;
+        }
+    }
+    return nil;
+}
+
+- (void)registerWXPlugins
+{
+    NSArray *plugins = pluginConfigs();
+    for (NSString *plugin in plugins) {
+        NSArray<NSString *> *pluginInfo = [plugin componentsSeparatedByString:@"&"];
+        if (pluginInfo.count != 2) {
+            continue;
+        }
+        NSString *className = [pluginInfo objectAtIndex:1];
+        if (!className.length) {
+            continue;
+        }
+        NSString *registerName = [pluginInfo objectAtIndex:0];
+        if (!registerName.length) {
+            continue;
+        }
+        Class pluginClass = NSClassFromString(className);
+        if (!pluginClass) {
+            continue;
+        }
+        // register the plugin
+        [self.plugins setObject:[[pluginClass alloc] init] forKey:registerName];
+    }
+}
+
+@end
diff --git a/ios/sdk/WeexSDK/Sources/Protocol/WXAppMonitorProtocol.h b/ios/sdk/WeexSDK/Sources/Protocol/WXAppMonitorProtocol.h
index 402fd8d..65f1b0d 100644
--- a/ios/sdk/WeexSDK/Sources/Protocol/WXAppMonitorProtocol.h
+++ b/ios/sdk/WeexSDK/Sources/Protocol/WXAppMonitorProtocol.h
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-#import "WXModuleProtocol.h"
+#import <WeexSDK/WXModuleProtocol.h>
 
 NS_ASSUME_NONNULL_BEGIN
 
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXVersion.m b/ios/sdk/WeexSDK/Sources/Utility/WXVersion.m
index d07a4d9..b435d18 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXVersion.m
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXVersion.m
@@ -20,8 +20,8 @@
 #import "WXVersion.h"
 #import "WXDefine.h"
 
-static const char* WeexSDKBuildTime = "2019-12-03 14:45:27 UTC";
-static const unsigned long WeexSDKBuildTimestamp = 1575384327;
+static const char* WeexSDKBuildTime = "2020-02-12 07:29:31 UTC";
+static const unsigned long WeexSDKBuildTimestamp = 1581492571;
 
 NSString* GetWeexSDKVersion(void)
 {
diff --git a/ios/sdk/WeexSDK/Sources/WeexSDK.h b/ios/sdk/WeexSDK/Sources/WeexSDK.h
index 05807f0..331ac78 100644
--- a/ios/sdk/WeexSDK/Sources/WeexSDK.h
+++ b/ios/sdk/WeexSDK/Sources/WeexSDK.h
@@ -56,6 +56,7 @@ FOUNDATION_EXPORT const unsigned char WeexSDKVersionString[];
 #import <WeexSDK/WXNavigationDefaultImpl.h>
 #import <WeexSDK/WXMonitor.h>
 #import <WeexSDK/WXModuleProtocol.h>
+#import <WeexSDK/WXModuleFactory.h>
 #import <WeexSDK/WXModalUIModule.h>
 #import <WeexSDK/WXLog.h>
 #import <WeexSDK/WXListComponent.h>
@@ -70,9 +71,10 @@ FOUNDATION_EXPORT const unsigned char WeexSDKVersionString[];
 #import <WeexSDK/WXExceptionUtils.h>
 #import <WeexSDK/WXEventModuleProtocol.h>
 #import <WeexSDK/WXErrorView.h>
+#import <WeexSDK/WXEaglePluginManager.h>
+#import <WeexSDK/WXEaglePlugin.h>
 #import <WeexSDK/WXDefine.h>
 #import <WeexSDK/WXDebugTool.h>
-#import <WeexSDK/WXDataRenderHandler.h>
 #import <WeexSDK/WXDarkSchemeProtocol.h>
 #import <WeexSDK/WXConvertUtility.h>
 #import <WeexSDK/WXConvert.h>
diff --git a/weex-playground b/weex-playground
index 75d1051..2cb8f27 160000
--- a/weex-playground
+++ b/weex-playground
@@ -1 +1 @@
-Subproject commit 75d10519cf4d05a2d133b07930aee3612f0cba3f
+Subproject commit 2cb8f2740fe51917f945c4423b6720c77beb95af
diff --git a/weex_core/Source/CMakeLists.txt b/weex_core/Source/CMakeLists.txt
index 19135ca..34da3c1 100755
--- a/weex_core/Source/CMakeLists.txt
+++ b/weex_core/Source/CMakeLists.txt
@@ -165,6 +165,7 @@ if(ANDROID)
     ./android/multiprocess/weex_js_connection.cpp
     ./android/utils/jni_load.cc
     ./core/bridge/eagle_bridge.cpp
+    ./core/bridge/eagle_bridge_ext.cpp
     ./core/network/android/default_request_handler.cc
   )
   SET(FINAL_ADD_LIBRARY
diff --git a/weex_core/Source/android/wrap/wx_bridge.cpp b/weex_core/Source/android/wrap/wx_bridge.cpp
index 756db51..f02f3e2 100755
--- a/weex_core/Source/android/wrap/wx_bridge.cpp
+++ b/weex_core/Source/android/wrap/wx_bridge.cpp
@@ -617,6 +617,11 @@ static jint CreateInstanceContext(JNIEnv* env, jobject jcaller,
   auto extraOptionString = base::android::ScopedLocalJavaRef<jstring>(
           env, getJsonData(env, args, 6));
 
+  auto script_type = std::unique_ptr<WXJSObject>(
+      new WXJSObject(env, base::android::ScopedLocalJavaRef<jobject>(
+          env, env->GetObjectArrayElement(args, 7))
+          .Get()));
+
 
   ScopedJStringUTF8 scoped_id(env, instanceId);
   ScopedJStringUTF8 scoped_func(env, function);
@@ -625,6 +630,8 @@ static jint CreateInstanceContext(JNIEnv* env, jobject jcaller,
   ScopedJStringUTF8 scoped_api(env, static_cast<jstring>(japi.Get()));
   ScopedJStringUTF8 scoped_render_strategy(
       env, static_cast<jstring>(render_strategy->GetData(env).Release()));
+  ScopedJStringUTF8 scoped_script_type(
+      env, static_cast<jstring>(script_type->GetData(env).Release()));
 
   ScopedJStringUTF8 scoped_extra_option(env, extraOptionString.Get());
   const std::string input = scoped_extra_option.getChars();
@@ -645,13 +652,12 @@ static jint CreateInstanceContext(JNIEnv* env, jobject jcaller,
     }
   }
 
-  // If strategy is DATA_RENDER_BINARY, jscript is a jbyteArray, otherwise jstring
-  // TODO use better way
   if (!WXBridge::Instance()->jni_object()) {
     WXBridge::Instance()->Reset(env, jcaller);
   }
-  if (scoped_render_strategy.getChars() != nullptr
-      && strcmp(scoped_render_strategy.getChars(), "DATA_RENDER_BINARY") == 0) {
+
+  if (scoped_script_type.getChars() != nullptr
+      && strcmp(scoped_script_type.getChars(), "binary") == 0) {
     JByteArrayRef byte_array(env, static_cast<jbyteArray>(jscript.Get()));
     return WeexCoreManager::Instance()
         ->getPlatformBridge()
@@ -740,69 +746,6 @@ static void onInteractionTimeUpdate(JNIEnv* env, jobject jcaller, jstring instan
   Java_WXBridge_onNativePerformanceDataUpdate(env,jcaller,instanceId,jni_map_performance);
 }
 
-static void FireEventOnDataRenderNode(JNIEnv* env, jobject jcaller,
-                                      jstring instanceId, jstring ref,
-                                      jstring type, jstring data,
-                                      jstring domChanges) {
-  if (instanceId == NULL || ref == NULL || type == NULL || data == NULL) {
-    return;
-  }
-
-  ScopedJStringUTF8 idChar(env, instanceId);
-  ScopedJStringUTF8 refChar(env, ref);
-  ScopedJStringUTF8 typeChar(env, type);
-  ScopedJStringUTF8 dataChar(env, data);
-  ScopedJStringUTF8 domChangesChar(env, domChanges);
-
-  WeexCore::EagleBridge::GetInstance()->data_render_handler()->FireEvent(
-      idChar.getChars(), refChar.getChars(), typeChar.getChars(),
-      dataChar.getChars(), domChangesChar.getChars()
-  );
-}
-
-static void InvokeCallbackOnDataRender(JNIEnv* env, jobject jcaller,
-                                       jstring instanceId, jstring callbackId,
-                                       jstring data, jboolean keepAlive) {
-  if (instanceId == NULL || callbackId == NULL || data == NULL) {
-    return;
-  }
-
-  ScopedJStringUTF8 idChar(env, instanceId);
-  ScopedJStringUTF8 callbackChar(env, callbackId);
-  ScopedJStringUTF8 dataChar(env, data);
-
-  WeexCore::EagleBridge::GetInstance()->data_render_handler()->InvokeCallback(
-      idChar.getChars(), callbackChar.getChars(), dataChar.getChars(),keepAlive);
-}
-
-static void RegisterModuleOnDataRenderNode(JNIEnv* env, jobject jcaller,
-                                      jstring data) {
-  if (data == NULL) {
-    return;
-  }
-
-  ScopedJStringUTF8 dataChar(env, data);
-
-  auto data_render_handler = WeexCore::EagleBridge::GetInstance()->data_render_handler();
-  if(data_render_handler){
-    data_render_handler->RegisterModules(
-        dataChar.getChars());
-  }
-}
-
-static void RegisterComponentOnDataRenderNode(JNIEnv* env, jobject jcaller,
-                                              jstring data) {
-  if (data == NULL) {
-    return;
-  }
-
-  ScopedJStringUTF8 dataChar(env, data);
-  auto data_render_handler = WeexCore::EagleBridge::GetInstance()->data_render_handler();
-  if(data_render_handler) {
-    data_render_handler->RegisterComponent(dataChar.getChars());
-  }
-}
-
 namespace WeexCore {
 
 WXBridge* WXBridge::g_instance = nullptr;
diff --git a/weex_core/Source/base/android/jniprebuild/jniheader/WXBridge_jni.h b/weex_core/Source/base/android/jniprebuild/jniheader/WXBridge_jni.h
index 3b68c16..3c54125 100755
--- a/weex_core/Source/base/android/jniprebuild/jniheader/WXBridge_jni.h
+++ b/weex_core/Source/base/android/jniprebuild/jniheader/WXBridge_jni.h
@@ -90,24 +90,6 @@ static jstring ExecJSOnInstance(JNIEnv *env, jobject jcaller,
 
 static void onInteractionTimeUpdate(JNIEnv *env, jobject jcaller, jstring instanceId);
 
-static void FireEventOnDataRenderNode(JNIEnv *env, jobject jcaller,
-                                      jstring instanceId,
-                                      jstring ref,
-                                      jstring type,
-                                      jstring data,
-                                      jstring domChanges);
-
-static void InvokeCallbackOnDataRender(JNIEnv *env, jobject jcaller,
-                                       jstring instanceId,
-                                       jstring callbackId,
-                                       jstring data,
-                                       jboolean keepAlive);
-
-static void RegisterModuleOnDataRenderNode(JNIEnv *env, jobject jcaller,
-                                           jstring data);
-
-static void RegisterComponentOnDataRenderNode(JNIEnv *env, jobject jcaller,
-                                              jstring data);
 static void TakeHeapSnapshot(JNIEnv *env, jobject jcaller,
                              jstring filename);
 
@@ -1236,33 +1218,6 @@ static const JNINativeMethod kMethodsWXBridge[] = {
      "Ljava/lang/String;"
      ")"
      "V", reinterpret_cast<void *>(onInteractionTimeUpdate)},
-    {"nativeFireEventOnDataRenderNode",
-     "("
-     "Ljava/lang/String;"
-     "Ljava/lang/String;"
-     "Ljava/lang/String;"
-     "Ljava/lang/String;"
-     "Ljava/lang/String;"
-     ")"
-     "V", reinterpret_cast<void *>(FireEventOnDataRenderNode)},
-    {"nativeInvokeCallbackOnDataRender",
-     "("
-     "Ljava/lang/String;"
-     "Ljava/lang/String;"
-     "Ljava/lang/String;"
-     "Z"
-     ")"
-     "V", reinterpret_cast<void *>(InvokeCallbackOnDataRender)},
-    {"nativeRegisterModuleOnDataRenderNode",
-     "("
-     "Ljava/lang/String;"
-     ")"
-     "V", reinterpret_cast<void *>(RegisterModuleOnDataRenderNode)},
-    {"nativeRegisterComponentOnDataRenderNode",
-     "("
-     "Ljava/lang/String;"
-     ")"
-     "V", reinterpret_cast<void *>(RegisterComponentOnDataRenderNode)},
     {"nativeTakeHeapSnapshot",
      "("
      "Ljava/lang/String;"
diff --git a/weex_core/Source/core/bridge/eagle_bridge.cpp b/weex_core/Source/core/bridge/eagle_bridge.cpp
index 10ee7a2..3a43911 100644
--- a/weex_core/Source/core/bridge/eagle_bridge.cpp
+++ b/weex_core/Source/core/bridge/eagle_bridge.cpp
@@ -17,250 +17,483 @@
  * under the License.
  */
 
+#include "third_party/json11/json11.hpp"
 #include "core/bridge/eagle_bridge.h"
+#include "base/string_util.h"
 #include "base/closure.h"
 #include "core/render/node/render_object.h"
 #include "core/render/node/factory/render_creator.h"
 #include "core/render/manager/render_manager.h"
 #include "core/manager/weex_core_manager.h"
 #include "core/network/http_module.h"
-#include "eagle_bridge.h"
-
 
 namespace WeexCore {
-    EagleBridge *EagleBridge::g_instance = nullptr;
-    
-    EagleRenderObject::EagleRenderObject():render_object_impl_(nullptr) {}
 
-    EagleRenderObject::EagleRenderObject(RenderObject* render_object):render_object_impl_(render_object) {}
+EagleBridge* EagleBridge::g_instance = nullptr;// NOLINT(cert-err58-cpp)
 
-    void EagleRenderObject::AddAttr(std::string key, std::string value) {
-        render_object_impl_->AddAttr(key, value);
-    }
-    
-    void EagleRenderObject::AddStyle(std::string key, std::string value) {
-        if (render_object_impl_->is_richtext_child()) {
-            render_object_impl_->MapInsertOrAssign(render_object_impl_->styles(), key, value);
-        } else {
-            render_object_impl_->AddStyle(key, value, false);
-        }
+void EagleBridge::CreatePage(const char* plugin_type,
+                             const char* instanceId,
+                             const char* func,
+                             const char* script,
+                             int script_length,
+                             const char* opts,
+                             const char* initData,
+                             const char* extendsApi, std::function<void(const char*, const char*)> callback) {
+  const auto& it = pages_.find(instanceId);
+  if (it == pages_.end()){
+    DataRenderHandler* plugin = get_data_render_handler(plugin_type);
+    if (!plugin) {
+      std::string err = std::string("EagleBridge plugin not exist: ") + plugin_type;
+      weex_core_handler()->ReportException(instanceId, "CreateInstance", err.c_str());
+      LOGE("%s", err.c_str());
+      return;
     }
 
-    void EagleRenderObject::UpdateAttr(std::string key, std::string value) {
-        render_object_impl_->UpdateAttr(key, value);
-    }
+    pages_[instanceId] = plugin;
+    plugin->CreatePage(instanceId, func, script, script_length, opts, initData, extendsApi, callback);
+  } else {
+    LOGE("ReCreate Page of InstanceId: %s", instanceId);
+  }
+}
 
-    void EagleRenderObject::UpdateStyle(std::string key, std::string value) {
-        render_object_impl_->UpdateStyle(key, value);
-    }
+EagleBridge::EagleBridge() : weex_core_handler_(new WeexCoreHandler()) {
 
-    void EagleRenderObject::AddEvent(std::string event) {
-        render_object_impl_->AddEvent(event);
-    }
+}
 
-    void EagleRenderObject::RemoveEvent(std::string event) {
-        render_object_impl_->RemoveEvent(event);
-    }
+EagleBridge::DataRenderHandler* EagleBridge::data_render_handler(const std::string& instance_id) const {
+  const auto& it = pages_.find(instance_id);
+  if (it == pages_.end()){
+    return nullptr;
+  } else {
+    return it->second;
+  }
+}
 
-    std::set<std::string>* EagleRenderObject::events() {
-        return render_object_impl_->events();
-    }
-    
-    void EagleRenderObject::set_page_id(const std::string& page_id) {
-        render_object_impl_->set_page_id(page_id);
-    }
-    
-    void EagleRenderObject::ApplyDefaultAttr() {
-        render_object_impl_->ApplyDefaultAttr();
-    }
-    
-    void EagleRenderObject::ApplyDefaultStyle() {
-        render_object_impl_->ApplyDefaultStyle(false);
-    }
-    
-    int EagleRenderObject::AddRenderObject(int index, EagleRenderObject child) {
-        if (!render_object_impl_) {
-            return -1;
-        }
-        return render_object_impl_->AddRenderObject(index, child.render_object_impl_);
-    }
+void EagleBridge::set_data_render_handler(const std::string& plugin_type,
+                                          DataRenderHandler* data_render_handler) {
+  std::lock_guard<std::mutex> lock(plugin_mutex_);
+  plugins_[plugin_type] = data_render_handler;
+}
 
-    int EagleRenderObject::getChildCount() {
-        return static_cast<int>(render_object_impl_->getChildCount());
-    }
+EagleBridge::DataRenderHandler* EagleBridge::get_data_render_handler(const std::string& plugin_type) {
+  std::lock_guard<std::mutex> lock(plugin_mutex_);
+  const auto& it = plugins_.find(plugin_type);
+  if (it == plugins_.end()) {
+    return nullptr;
+  } else {
+    return it->second;
+  }
+}
 
-    int EagleRenderObject::getChildIndex(EagleRenderObject child) {
-        return static_cast<int>(render_object_impl_->IndexOf(child.render_object_impl_));
-    }
+EagleBridge* EagleBridge::GetInstance() {
+  static std::once_flag s_flag;
+  std::call_once(s_flag, []() {
+    g_instance = new EagleBridge();
+  });
 
-    EagleRenderObject EagleRenderObject::GetChild(int index) {
-        return render_object_impl_->GetChild(index);
-    }
+  return g_instance;
+}
 
-    void EagleRenderObject::set_is_richtext_child(const bool is_richtext_child) {
-        render_object_impl_->set_is_richtext_child(is_richtext_child);
-    }
+EagleModeReturn EagleBridge::DestroyPage(const char* instanceId) {
+  const auto& it = pages_.find(instanceId);
+  if (it == pages_.end()){
+    return EagleModeReturn::NOT_EAGLE;
+  } else {
+    EagleModeReturn mode = it->second->DestroyInstance(instanceId);
+    pages_.erase(it);
+    return mode;
+  }
+}
 
-    EagleRenderObject EagleRenderObject::parent_render(){
-        return render_object_impl_->parent_render();
-    }
+EagleModeReturn EagleBridge::RefreshPage(const char* instanceId, const char* initData) {
+  const auto& it = pages_.find(instanceId);
+  if (it == pages_.end()){
+    return EagleModeReturn::NOT_EAGLE;
+  } else {
+    return it->second->RefreshPage(instanceId, initData);;
+  }
+}
 
-    const std::string& EagleRenderObject::page_id(){
-        return render_object_impl_->page_id();
-    }
+void EagleBridge::UpdateComponentData(const char* instanceId, const char* cid, const char* json_data) {
+  const auto& it = pages_.find(instanceId);
+  if (it == pages_.end()){
+    weex_core_handler()->ReportException(
+        instanceId, "UpdateComponentData",
+        "There is no data_render_handler when UpdateComponentData invoked");
+    return;
+  } else {
+    return it->second->UpdateComponentData(instanceId, cid, json_data);;
+  }
+}
 
-    const std::string& EagleRenderObject::ref(){
-        return render_object_impl_->ref();
-    }
+bool EagleBridge::CallEagleTaskFromWeex(const char* instanceId,
+                                        const char* task,
+                                        const char* options) {
+  if (instanceId){
+    //a single instance task
+    const auto& it = pages_.find(instanceId);
+    if (it == pages_.end()){
+      return false;
+    } else {
+      return it->second->CallEagleTaskFromWeex(instanceId, task, options);
+    }
+  } else {
+    //a global task; call every plugins.
+    bool support = false;
+    for (const auto& it: plugins_){
+      support = support || it.second->CallEagleTaskFromWeex(nullptr, task ,options);
+    }
+    return support;
+  }
+  return false;
+}
 
-    void EagleRenderObject::RemoveRenderObject(EagleRenderObject child) {
-        render_object_impl_->RemoveRenderObject(child.render_object_impl_);
-    }
+EagleRenderObject::EagleRenderObject() : render_object_impl_(nullptr) {}
 
-    EagleRenderObject EagleBridge::WeexCoreHandler::GetEagleRenderObject(const std::string &type, const std::string &ref) {
-        return EagleRenderObject(static_cast<WeexCore::RenderObject*>(WeexCore::RenderCreator::GetInstance()->CreateRender(type, ref)));
-    }
-    
-    bool EagleBridge::WeexCoreHandler::CreatePage(const std::string& page_id, EagleRenderObject root) {
-        return RenderManager::GetInstance()->CreatePage(page_id, root.render_object_impl_);
-    }
+EagleRenderObject::EagleRenderObject(RenderObject* render_object) : render_object_impl_(
+    render_object) {}
 
-    bool EagleBridge::WeexCoreHandler::HavePage(const std::string& page_id) {
-        return RenderManager::GetInstance()->GetPage(page_id) ? true : false;
-    }
-    
-    bool EagleBridge::WeexCoreHandler::CreateFinish(const std::string &page_id) {
-        return RenderManager::GetInstance()->CreateFinish(page_id);
-    }
-    
-    bool EagleBridge::WeexCoreHandler::ClosePage(const std::string &page_id) {
-        return RenderManager::GetInstance()->ClosePage(page_id);
-    }
-    
-    void EagleBridge::WeexCoreHandler::ReportException(const char* page_id, const char* func, const char* exception_string) {
-        WeexCore::WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->ReportException(page_id, func, exception_string);
-    }
-    
-    void EagleBridge::WeexCoreHandler::Send(const char* instance_id, const char* url, std::function<void(const std::string&, const std::string&)> callback) {
-        weex::core::network::HttpModule http_module;
-        http_module.Send(instance_id, url, callback);
-    }
+void EagleRenderObject::AddAttr(const std::string& key, const std::string& value) {
+  render_object_impl_->AddAttr(key, value);
+}
 
-    void EagleBridge::WeexCoreHandler::GetBundleType(const char* instance_id, const char* content, std::function<void(const std::string&, const std::string&)> callback) {
-        weex::core::network::HttpModule http_module;
-        http_module.GetBundleType(instance_id, content, callback);
-    }
-    
-    int EagleBridge::WeexCoreHandler::RefreshFinish(const char* page_id, const char* task, const char* callback) {
-      WeexCore::WeexCoreManager::Instance()
-          ->getPlatformBridge()
-          ->core_side()->ForceLayout(page_id);
-        return WeexCore::WeexCoreManager::Instance()
-        ->getPlatformBridge()
-        ->platform_side()
-        ->RefreshFinish(page_id, task, callback);
-    }
-    
-    std::unique_ptr<ValueWithType> EagleBridge::WeexCoreHandler::CallNativeModule(const char* page_id, const char* module, const char* method,const char* arguments, int arguments_length, const char* options, int options_length) {
-        return WeexCoreManager::Instance()
-        ->getPlatformBridge()
-        ->platform_side()
-        ->CallNativeModule(page_id, module, method, arguments, arguments_length, options, options_length);
-    }
-#if OS_IOS
-    std::unique_ptr<ValueWithType> EagleBridge::WeexCoreHandler::RegisterPluginModule(const std::string &name, const std::string &class_name, const std::string &version) {
-        return WeexCoreManager::Instance()
-        ->getPlatformBridge()
-        ->platform_side()
-        ->RegisterPluginModule(name.c_str(), class_name.c_str(), version.c_str());
-    }
-    std::unique_ptr<ValueWithType> EagleBridge::WeexCoreHandler::RegisterPluginComponent(const std::string &name, const std::string &class_name, const std::string &version) {
-        return WeexCoreManager::Instance()
-        ->getPlatformBridge()
-        ->platform_side()
-        ->RegisterPluginComponent(name.c_str(), class_name.c_str(), version.c_str());
-    }
+void EagleRenderObject::AddStyle(const std::string& key, const std::string& value) {
+  if (render_object_impl_->is_richtext_child()) {
+    render_object_impl_->MapInsertOrAssign(render_object_impl_->styles(), key, value);
+  } else {
+    render_object_impl_->AddStyle(key, value, false);
+  }
+}
 
-    void EagleBridge::WeexCoreHandler::PostTaskOnComponentThread(const weex::base::Closure& closure) {
-        WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->PostTaskOnComponentThread(closure);
-    }
+void EagleRenderObject::UpdateAttr(const std::string& key, const std::string& value) {
+  render_object_impl_->UpdateAttr(key, value);
+}
+
+void EagleRenderObject::UpdateStyle(const std::string& key, const std::string& value) {
+  render_object_impl_->UpdateStyle(key, value);
+}
+
+void EagleRenderObject::AddEvent(const std::string& event) {
+  render_object_impl_->AddEvent(event);
+}
+
+void EagleRenderObject::RemoveEvent(const std::string& event) {
+  render_object_impl_->RemoveEvent(event);
+}
+
+std::set<std::string>* EagleRenderObject::events() {
+  return render_object_impl_->events();
+}
+
+void EagleRenderObject::set_page_id(const std::string& page_id) {
+  render_object_impl_->set_page_id(page_id);
+}
+
+void EagleRenderObject::ApplyDefaultAttr() {
+  render_object_impl_->ApplyDefaultAttr();
+}
+
+void EagleRenderObject::ApplyDefaultStyle() {
+  render_object_impl_->ApplyDefaultStyle(false);
+}
+
+int EagleRenderObject::AddRenderObject(int index, EagleRenderObject child) {
+  if (!render_object_impl_) {
+    return -1;
+  }
+  return render_object_impl_->AddRenderObject(index, child.render_object_impl_);
+}
+
+int EagleRenderObject::getChildCount() {
+  return static_cast<int>(render_object_impl_->getChildCount());
+}
+
+int EagleRenderObject::getChildIndex(EagleRenderObject child) {
+  return static_cast<int>(render_object_impl_->IndexOf(child.render_object_impl_));
+}
+
+EagleRenderObject EagleRenderObject::GetChild(int index) {
+  return render_object_impl_->GetChild(index);
+}
+
+void EagleRenderObject::set_is_richtext_child(const bool is_richtext_child) {
+  render_object_impl_->set_is_richtext_child(is_richtext_child);
+}
+
+EagleRenderObject EagleRenderObject::parent_render() {
+  return render_object_impl_->parent_render();
+}
+
+const std::string& EagleRenderObject::page_id() {
+  return render_object_impl_->page_id();
+}
+
+const std::string& EagleRenderObject::ref() {
+  return render_object_impl_->ref();
+}
+
+void EagleRenderObject::RemoveRenderObject(EagleRenderObject child) {
+  render_object_impl_->RemoveRenderObject(child.render_object_impl_);
+}
+
+EagleRenderObject EagleBridge::WeexCoreHandler::GetEagleRenderObject(const std::string& type,
+                                                                     const std::string& ref) {
+  return EagleRenderObject(
+      static_cast<WeexCore::RenderObject*>(WeexCore::RenderCreator::GetInstance()->CreateRender(
+          type, ref)));
+}
+
+bool EagleBridge::WeexCoreHandler::CreatePage(const std::string& page_id, EagleRenderObject root) {
+  return RenderManager::GetInstance()->CreatePage(page_id, root.render_object_impl_);
+}
+
+bool EagleBridge::WeexCoreHandler::HavePage(const std::string& page_id) {
+  return RenderManager::GetInstance()->GetPage(page_id) ? true : false;
+}
+
+bool EagleBridge::WeexCoreHandler::CreateFinish(const std::string& page_id) {
+  return RenderManager::GetInstance()->CreateFinish(page_id);
+}
+
+bool EagleBridge::WeexCoreHandler::ClosePage(const std::string& page_id) {
+  return RenderManager::GetInstance()->ClosePage(page_id);
+}
+
+void EagleBridge::WeexCoreHandler::ReportException(const char* page_id,
+                                                   const char* func,
+                                                   const char* exception_string) {
+  WeexCore::WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->ReportException(
+      page_id, func, exception_string);
+}
+
+void EagleBridge::WeexCoreHandler::Send(const char* instance_id,
+                                        const char* url,
+                                        std::function<void(const std::string&,
+                                                           const std::string&)> callback) {
+  weex::core::network::HttpModule http_module;
+  http_module.Send(instance_id, url, callback);
+}
+
+void EagleBridge::WeexCoreHandler::GetBundleType(const char* instance_id,
+                                                 const char* content,
+                                                 std::function<void(const std::string&,
+                                                                    const std::string&)> callback) {
+  weex::core::network::HttpModule http_module;
+  http_module.GetBundleType(instance_id, content, callback);
+}
+
+//void EagleBridge::WeexCoreHandler::RequrieMoudle(const std::string& class_name) {
+//}
+
+//void EagleBridge::WeexCoreHandler::RequrieComponent(const std::string& class_name) {
+//}
+
+bool EagleBridge::WeexCoreHandler::RefreshFinish(const char* page_id,
+                                                 const char* task,
+                                                 const char* callback) {
+  WeexCore::WeexCoreManager::Instance()
+      ->getPlatformBridge()
+      ->core_side()->ForceLayout(page_id);
+  return static_cast<bool>(WeexCore::WeexCoreManager::Instance()
+      ->getPlatformBridge()
+      ->platform_side()
+      ->RefreshFinish(page_id, task, callback));
+}
+
+//return empty for undefined
+static std::string ParsePlatformResultToString(const std::unique_ptr<ValueWithType>& result) {
+  switch (result->type) {
+    case ParamsType::DOUBLE:
+      return json11::Json(result->value.doubleValue).dump();
+    case ParamsType::STRING: {
+      if (!result->value.string) {
+        return "";
+      } else {
+        std::string ret;
+        if (result->value.string->length > 0) {
+          const auto& basic_string = weex::base::to_utf8(result->value.string->content,
+                                                         result->value.string->length);
+          ret = json11::Json(basic_string).dump();
+        } else {
+          ret = json11::Json("").dump();
+        }
+        free(result->value.string);
+        return ret;
+      }
+    }
+    case ParamsType::BYTEARRAYSTRING: {
+      if (!result->value.byteArray) {
+        return "";//null
+      } else {
+        std::string ret;
+        if (result->value.byteArray->length > 0) {
+          ret = json11::Json(result->value.byteArray->content).dump();
+        } else {
+          ret = json11::Json("").dump();
+        }
+        free(result->value.byteArray);
+        return ret;
+      }
+    }
+    case ParamsType::JSONSTRING: {
+      if (!result->value.string) {
+        return "";
+      } else {
+        std::string ret;
+        std::string err;
+        if (result->value.string->length > 0) {
+          const auto& raw_str = weex::base::to_utf8(result->value.string->content,
+                                                    result->value.string->length);
+
+          const json11::Json& json = json11::Json::parse(raw_str, err);
+          if (err.empty()) {
+            //succ
+            ret = json.dump();
+          } else {
+            LOGE("VnodeManager CallNative return value to object err, %s", err.c_str());
+          }
+        }
+        free(result->value.string);
+        return ret;
+      }
+    }
+    case ParamsType::BYTEARRAYJSONSTRING: {
+      if (!result->value.byteArray) {
+        return "";
+      } else {
+        std::string ret;
+        std::string err;
+        if (result->value.string->length > 0) {
+          const json11::Json& json = json11::Json::parse(result->value.byteArray->content, err);
+          if (err.empty()) {
+            //succ
+            ret = json.dump();
+          } else {
+            LOGE("VnodeManager CallNative return value to object err, %s", err.c_str());
+          }
+        }
+        free(result->value.byteArray);
+        return ret;
+      }
+    }
+    case ParamsType::BYTEARRAY:
+    default:
+      return "";
+  }
+}
+
+std::string EagleBridge::WeexCoreHandler::CallNativeModule(const char* page_id,
+                                                           const char* module,
+                                                           const char* method,
+                                                           const char* arguments,
+                                                           int arguments_length,
+                                                           const char* options,
+                                                           int options_length) {
+  auto ptr = WeexCoreManager::Instance()
+      ->getPlatformBridge()
+      ->platform_side()
+      ->CallNativeModule(page_id, module, method, arguments, arguments_length, options,
+                         options_length);
+  return ParsePlatformResultToString(ptr);
+}
+
+#if OS_IOS
+void EagleBridge::WeexCoreHandler::PostTaskOnComponentThread(const weex::base::Closure& closure) {
+    WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->PostTaskOnComponentThread(closure);
+}
 #endif
-    void EagleBridge::WeexCoreHandler::CallNativeComponent(const char* page_id, const char* module, const char* method,const char* arguments, int arguments_length, const char* options, int options_length) {
-        WeexCoreManager::Instance()
-        ->getPlatformBridge()
-        ->platform_side()
-        ->CallNativeComponent(page_id, module, method, arguments, arguments_length, options, options_length);
-    }
-    
-    void EagleBridge::WeexCoreHandler::NativeLog(const char* str_array) {
-        WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->NativeLog(str_array);
-    }
-    
-    bool EagleBridge::WeexCoreHandler::RemoveRenderObject(const std::string &page_id, const std::string &ref) {
-        return RenderManager::GetInstance()->RemoveRenderObject(page_id, ref);
-    }
-    
-    bool EagleBridge::WeexCoreHandler::AddRenderObject(const std::string &page_id, const std::string &parent_ref, int index, EagleRenderObject root) {
-        return RenderManager::GetInstance()->AddRenderObject(page_id, parent_ref, index, root.render_object_impl_);
-    }
-    
-    bool EagleBridge::WeexCoreHandler::MoveRenderObject(const std::string &page_id, const std::string &ref,const std::string &parent_ref, int index) {
-        return RenderManager::GetInstance()->MoveRenderObject(page_id, ref, parent_ref, index);
-    }
-    
-    bool EagleBridge::WeexCoreHandler::RemoveEvent(const std::string &page_id, const std::string &ref,
-                                  const std::string &event) {
-        return RenderManager::GetInstance()->RemoveEvent(page_id, ref, event);
-    }
-    
-    bool EagleBridge::WeexCoreHandler::AddEvent(const std::string &page_id, const std::string &ref,
-                               const std::string &event) {
-        return RenderManager::GetInstance()->AddEvent(page_id, ref, event);
-    }
-    
-    bool EagleBridge::WeexCoreHandler::UpdateAttr(const std::string &page_id, const std::string &ref,
-                    const char *data) {
-        return RenderManager::GetInstance()->UpdateAttr(page_id, ref, data);
-    }
-    
-    bool EagleBridge::WeexCoreHandler::UpdateAttr(const std::string &page_id, const std::string &ref,
-                                 std::vector<std::pair<std::string, std::string>> *attrPair) {
-        return RenderManager::GetInstance()->UpdateAttr(page_id, ref, attrPair);
-    }
-    
-    bool EagleBridge::WeexCoreHandler::UpdateStyle(const std::string &page_id, const std::string &ref,
-                                  const char *data) {
-        return RenderManager::GetInstance()->UpdateStyle(page_id, ref, data);
-    }
-    
-    bool EagleBridge::WeexCoreHandler::UpdateStyle(const std::string &page_id, const std::string &ref,
-                                  std::vector<std::pair<std::string, std::string>> *stylePair) {
-        return RenderManager::GetInstance()->UpdateStyle(page_id, ref, stylePair);
-    }
 
-    int EagleBridge::WeexCoreHandler::ExecJS(const char *instanceId, const char *nameSpace,
-                       const char *func,
-                       std::vector<VALUE_WITH_TYPE *> &params){
-        return WeexCore::WeexCoreManager::Instance()->script_bridge()->script_side()->ExecJS(
-            instanceId,
-            nameSpace,
-            func,
-            params
-        );
-    }
+void EagleBridge::WeexCoreHandler::CallNativeComponent(const char* page_id,
+                                                       const char* module,
+                                                       const char* method,
+                                                       const char* arguments,
+                                                       int arguments_length,
+                                                       const char* options,
+                                                       int options_length) {
+  WeexCoreManager::Instance()
+      ->getPlatformBridge()
+      ->platform_side()
+      ->CallNativeComponent(page_id, module, method, arguments, arguments_length, options,
+                            options_length);
+}
 
-    //FIXME Please don't call this method, which will cause downgrade of Weex.
-    void EagleBridge::WeexCoreHandler::PostTaskToMsgLoop(const weex::base::Closure& closure){
-        WeexCore::WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->ReportException(
-            "", "PostTaskToMsgLoop",
-            "PostTaskToMsgLoop is not supported anymore, please update to the latest version of Weex.");
-    }
-    
-    int EagleBridge::DataRenderHandler::DestroyInstance(const char *instanceId) {
-        return WeexCoreManager::Instance()
-        ->script_bridge()
-        ->script_side()
-        ->DestroyInstance(instanceId);
-    }
+void EagleBridge::WeexCoreHandler::NativeLog(const char* str_array) {
+  WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->NativeLog(str_array);
+}
+
+bool EagleBridge::WeexCoreHandler::RemoveRenderObject(const std::string& page_id,
+                                                      const std::string& ref) {
+  return RenderManager::GetInstance()->RemoveRenderObject(page_id, ref);
+}
+
+bool EagleBridge::WeexCoreHandler::AddRenderObject(const std::string& page_id,
+                                                   const std::string& parent_ref,
+                                                   int index,
+                                                   EagleRenderObject root) {
+  return RenderManager::GetInstance()->AddRenderObject(page_id, parent_ref, index,
+                                                       root.render_object_impl_);
+}
+
+bool EagleBridge::WeexCoreHandler::MoveRenderObject(const std::string& page_id,
+                                                    const std::string& ref,
+                                                    const std::string& parent_ref,
+                                                    int index) {
+  return RenderManager::GetInstance()->MoveRenderObject(page_id, ref, parent_ref, index);
+}
+
+bool EagleBridge::WeexCoreHandler::RemoveEvent(const std::string& page_id, const std::string& ref,
+                                               const std::string& event) {
+  return RenderManager::GetInstance()->RemoveEvent(page_id, ref, event);
+}
+
+bool EagleBridge::WeexCoreHandler::AddEvent(const std::string& page_id, const std::string& ref,
+                                            const std::string& event) {
+  return RenderManager::GetInstance()->AddEvent(page_id, ref, event);
+}
+
+bool EagleBridge::WeexCoreHandler::UpdateAttr(const std::string& page_id, const std::string& ref,
+                                              const char* data) {
+  return RenderManager::GetInstance()->UpdateAttr(page_id, ref, data);
+}
+
+bool EagleBridge::WeexCoreHandler::UpdateAttr(const std::string& page_id, const std::string& ref,
+                                              std::vector<std::pair<std::string, std::string>>* attrPair) {
+  return RenderManager::GetInstance()->UpdateAttr(page_id, ref, attrPair);
+}
+
+bool EagleBridge::WeexCoreHandler::UpdateStyle(const std::string& page_id, const std::string& ref,
+                                               const char* data) {
+  return RenderManager::GetInstance()->UpdateStyle(page_id, ref, data);
+}
+
+bool EagleBridge::WeexCoreHandler::UpdateStyle(const std::string& page_id, const std::string& ref,
+                                               std::vector<std::pair<std::string, std::string>>* stylePair) {
+  return RenderManager::GetInstance()->UpdateStyle(page_id, ref, stylePair);
+}
+
+int EagleBridge::WeexCoreHandler::ExecJS(const char* instanceId, const char* nameSpace,
+                                         const char* func,
+                                         std::vector<ValueWithType*>& params) {
+  return WeexCore::WeexCoreManager::Instance()->script_bridge()->script_side()->ExecJS(
+      instanceId,
+      nameSpace,
+      func,
+      params
+  );
+}
+
+//FIXME Please don't call this method, which will cause downgrade of Weex.
+void EagleBridge::WeexCoreHandler::PostTaskToMsgLoop(const weex::base::Closure& closure) {
+  WeexCore::WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->ReportException(
+      "", "PostTaskToMsgLoop",
+      "PostTaskToMsgLoop is not supported anymore, please update to the latest version of Weex.");
+}
+
+bool EagleBridge::WeexCoreHandler::CallWeexTaskFromEagle(const std::string& type,
+                                                         const std::string& task,
+                                                         const std::string& options) {
+  //No Extend Method now.
+  return false;
+}
 }
 
diff --git a/weex_core/Source/core/bridge/eagle_bridge.h b/weex_core/Source/core/bridge/eagle_bridge.h
index 80e5630..1f20c29 100644
--- a/weex_core/Source/core/bridge/eagle_bridge.h
+++ b/weex_core/Source/core/bridge/eagle_bridge.h
@@ -21,135 +21,227 @@
 #define CORE_BRIDGE_EAGLE_BRIDGE_H
 
 #if defined __cplusplus
+
 #include <string>
+#include <map>
 #include <functional>
 #include <set>
+#include <mutex>
 
 struct ValueWithType;
 namespace WeexCore {
-    class RenderObject;
-    class DataRenderHandler;
-    
-    class EagleRenderObject {
-    public:
-        friend class EagleBridge;
-        EagleRenderObject();
-        EagleRenderObject(RenderObject* render_object);
-        void AddAttr(std::string key, std::string value);
-        void AddStyle(std::string key, std::string value);
-        void UpdateAttr(std::string key, std::string value);
-        void UpdateStyle(std::string key, std::string value);
-        void AddEvent(std::string event);
-        void RemoveEvent(std::string event);
-        void set_is_richtext_child(const bool is_richtext_child);
-        std::set<std::string> *events();
-        
-        void set_page_id(const std::string& page_id);
-        void ApplyDefaultStyle();
-        void ApplyDefaultAttr();
-        int getChildCount();
-        int getChildIndex(EagleRenderObject child);
-        EagleRenderObject GetChild(int index);
-        EagleRenderObject parent_render();
-        int AddRenderObject(int index, EagleRenderObject child);
-        void RemoveRenderObject(EagleRenderObject child);
-        const std::string& page_id();
-        const std::string& ref();
-
-        bool operator ==(const EagleRenderObject& object) const {
-            return render_object_impl_ == object.render_object_impl_;
-        }
-        explicit operator bool() const
-        {
-            return static_cast<bool>(render_object_impl_);
-        }
-
-    private:
-        RenderObject* render_object_impl_;
-    };
-
-    class EagleBridge {
-    public:
-        class WeexCoreHandler {
-        public:
-            EagleRenderObject GetEagleRenderObject(const std::string &type, const std::string &ref);
-            bool CreatePage(const std::string& page_id, EagleRenderObject root);
-            bool HavePage(const std::string& page_id);
-            bool CreateFinish(const std::string &page_id);
-            bool ClosePage(const std::string &page_id);
-            void ReportException(const char* page_id, const char* func, const char* exception_string);
-            void Send(const char* instance_id, const char* url, std::function<void(const std::string&, const std::string&)> callback);
-            void GetBundleType(const char* instance_id, const char* url, std::function<void(const std::string&, const std::string&)> callback);
-            int RefreshFinish(const char* page_id, const char* task, const char* callback);
-            std::unique_ptr<ValueWithType> CallNativeModule (const char* page_id, const char* module, const char* method,const char* arguments, int arguments_length, const char* options, int options_length);
-            void CallNativeComponent (const char* page_id, const char* module, const char* method,const char* arguments, int arguments_length, const char* options, int options_length);
-            void NativeLog(const char* str_array);
-            bool RemoveRenderObject(const std::string &page_id, const std::string &ref);
-            bool AddRenderObject(const std::string &page_id, const std::string &parent_ref, int index,EagleRenderObject root);
-            bool MoveRenderObject(const std::string &page_id, const std::string &ref,const std::string &parent_ref, int index);
-            bool RemoveEvent(const std::string &page_id, const std::string &ref,
-                             const std::string &event);
-            bool AddEvent(const std::string &page_id, const std::string &ref,
-                          const std::string &event);
-            bool UpdateAttr(const std::string &page_id, const std::string &ref,
-                            const char *data);
-            
-            bool UpdateAttr(const std::string &page_id, const std::string &ref,
-                            std::vector<std::pair<std::string, std::string>> *attrPair);
-            
-            bool UpdateStyle(const std::string &page_id, const std::string &ref,
-                             const char *data);
-            
-            bool UpdateStyle(const std::string &page_id, const std::string &ref,
-                             std::vector<std::pair<std::string, std::string>> *stylePair);
-
-            int ExecJS(const char *instanceId, const char *nameSpace,
-                       const char *func,
-                       std::vector<struct ValueWithType *> &params);
-            void PostTaskToMsgLoop(const std::function<void()>& closure);
-#if OS_IOS
-            std::unique_ptr<ValueWithType> RegisterPluginModule(const std::string &name, const std::string &class_name, const std::string &version);
-            std::unique_ptr<ValueWithType> RegisterPluginComponent(const std::string &name, const std::string &class_name, const std::string &version);
-            void PostTaskOnComponentThread(const std::function<void()>& closure);
+
+enum class EagleModeReturn {
+  NOT_EAGLE = 0,
+  EAGLE_ONLY = 1,
+  EAGLE_AND_SCRIPT = 2
+};
+
+class RenderObject;
+
+class EagleRenderObject {
+ public:
+  friend class EagleBridge;
+
+  EagleRenderObject();
+  EagleRenderObject(RenderObject* render_object);
+  void AddAttr(const std::string& key, const std::string& value);
+  void AddStyle(const std::string& key, const std::string& value);
+  void UpdateAttr(const std::string& key, const std::string& value);
+  void UpdateStyle(const std::string& key, const std::string& value);
+  void AddEvent(const std::string& event);
+  void RemoveEvent(const std::string& event);
+  void set_is_richtext_child(const bool is_richtext_child);
+  std::set<std::string>* events();
+
+  void set_page_id(const std::string& page_id);
+  void ApplyDefaultStyle();
+  void ApplyDefaultAttr();
+  int getChildCount();
+  int getChildIndex(EagleRenderObject child);
+  EagleRenderObject GetChild(int index);
+  EagleRenderObject parent_render();
+  int AddRenderObject(int index, EagleRenderObject child);
+  void RemoveRenderObject(EagleRenderObject child);
+  const std::string& page_id();
+  const std::string& ref();
+
+  bool operator==(const EagleRenderObject& object) const {
+    return render_object_impl_ == object.render_object_impl_;
+  }
+  explicit operator bool() const {
+    return static_cast<bool>(render_object_impl_);
+  }
+
+ private:
+  RenderObject* render_object_impl_;
+};
+
+class EagleBridge {
+ public:
+  class WeexCoreHandler {
+   public:
+    EagleRenderObject GetEagleRenderObject(const std::string& type, const std::string& ref);
+    bool CreatePage(const std::string& page_id, EagleRenderObject root);
+    bool HavePage(const std::string& page_id);
+    bool CreateFinish(const std::string& page_id);
+    bool RefreshFinish(const char* page_id, const char* task, const char* callback);
+    bool ClosePage(const std::string& page_id);
+
+    void NativeLog(const char* str_array);
+    void ReportException(const char* page_id, const char* func, const char* exception_string);
+
+    bool RemoveRenderObject(const std::string& page_id, const std::string& ref);
+    bool AddRenderObject(const std::string& page_id,
+                         const std::string& parent_ref,
+                         int index,
+                         EagleRenderObject root);
+    bool MoveRenderObject(const std::string& page_id,
+                          const std::string& ref,
+                          const std::string& parent_ref,
+                          int index);
+    bool RemoveEvent(const std::string& page_id, const std::string& ref,
+                     const std::string& event);
+    bool AddEvent(const std::string& page_id, const std::string& ref,
+                  const std::string& event);
+    bool UpdateAttr(const std::string& page_id, const std::string& ref,
+                    const char* data);
+
+    bool UpdateAttr(const std::string& page_id, const std::string& ref,
+                    std::vector<std::pair<std::string, std::string>>* attrPair);
+
+    bool UpdateStyle(const std::string& page_id, const std::string& ref,
+                     const char* data);
+
+    bool UpdateStyle(const std::string& page_id, const std::string& ref,
+                     std::vector<std::pair<std::string, std::string>>* stylePair);
+
+    //vue api
+    int ExecJS(const char* instanceId, const char* nameSpace,
+               const char* func,
+               std::vector<struct ValueWithType*>& params);
+
+    void PostTaskToMsgLoop(const std::function<void()>& closure);
+
+#if  OS_IOS
+    void PostTaskOnComponentThread(const std::function<void()>& closure);
 #endif
-        };
-        
-        class DataRenderHandler {
-        public:
-            virtual int DestroyInstance(const char *instanceId);
-            virtual void CreatePage(const std::string &input, const std::string &page_id, const std::string &options, const std::string &init_data, std::function<void(const char*, const char*)> exec_js) {}
-            
-            virtual void CreatePage(const char *contents, size_t length, const std::string& page_id, const std::string& options, const std::string& env, const std::string& init_data, std::function<void(const char*,const char*)> exec_js) {}
-            virtual bool RefreshPage(const std::string &page_id, const std::string &init_data) {return false;}
-            virtual void UpdateComponentData(const std::string& page_id, const char* cid, const std::string& json_data) {}
-            virtual void FireEvent(const std::string &page_id, const std::string &ref, const std::string &event,const std::string &args,const std::string &dom_changes) {}
-            virtual void InvokeCallback(const std::string& page_id,
-                                      const std::string& callback_id,
-                                      const std::string& data,
-                                      bool keep_alive) {}
-            virtual void RegisterModules(const std::string &modules) {}
-            virtual void RegisterComponent(const std::string &str) {};
-            virtual void DispatchPageLifecycle(const std::string &page_id) {};
-        };
-        
-        static EagleBridge* GetInstance() {
-            if (!g_instance) {
-                g_instance = new EagleBridge();
-            }
-            return g_instance;
-        }
-        DataRenderHandler *data_render_handler() const {return data_render_handler_.get();}
-        void set_data_render_handler(DataRenderHandler *data_render_handler) {data_render_handler_.reset(data_render_handler);}
-        WeexCoreHandler* weex_core_handler() const {return weex_core_handler_.get();}
-        
-
-    private:
-        EagleBridge() : weex_core_handler_(new WeexCoreHandler()) {}
-        static EagleBridge *g_instance;
-        std::unique_ptr<DataRenderHandler> data_render_handler_;
-        std::unique_ptr<WeexCoreHandler> weex_core_handler_;
-    };
+    void Send(const char* instance_id,
+              const char* url,
+              std::function<void(const std::string&, const std::string&)> callback);
+
+    void GetBundleType(const char* instance_id,
+                       const char* url,
+                       std::function<void(const std::string&, const std::string&)> callback);
+
+    //rax api
+//    void RequrieMoudle(const std::string& class_name);
+
+//    void RequrieComponent(const std::string& class_name);
+
+    std::string CallNativeModule(const char* page_id,
+                                 const char* module,
+                                 const char* method,
+                                 const char* arguments,
+                                 int arguments_length,
+                                 const char* options,
+                                 int options_length);
+    void CallNativeComponent(const char* page_id,
+                             const char* module,
+                             const char* method,
+                             const char* arguments,
+                             int arguments_length,
+                             const char* options,
+                             int options_length);
+
+    //扩展方法. type是plugin的name, bool返回值代表switch分支是否包含当前task.
+    bool CallWeexTaskFromEagle(const std::string& type,
+                               const std::string& task,
+                               const std::string& options);
+  };
+
+  class DataRenderHandler {
+   public:
+    //如果plugin不存在则ReportException.
+    virtual void CreatePage(const char* instanceId,
+                            const char* func,
+                            const char* script,
+                            int script_length,
+                            const char* opts,
+                            const char* initData,
+                            const char* extendsApi, std::function<void(const char*, const char*)> function) = 0;
+
+    virtual EagleModeReturn RefreshPage(const char*  page_id,
+                                        const char*  init_data) = 0;
+
+    virtual EagleModeReturn DestroyInstance(const char* instanceId) = 0;
+
+    virtual void UpdateComponentData(const char* instanceId,
+                                     const char* cid,
+                                     const char* json_data) = 0;
+
+    // 这些方法应该走Java层, 然后在plugin内部的jni处理.
+    // virtual void FireEvent(const std::string &page_id, const std::string &ref, const std::string &event,const std::string &args,const std::string &dom_changes) {}
+    // virtual void InvokeCallback(const std::string& page_id,
+    //                           const std::string& callback_id,
+    //                           const std::string& data,
+    //                           bool keep_alive) {}
+    // virtual void RegisterModules(const std::string &modules) {}
+    // virtual void RegisterComponent(const std::string &str) {};
+
+
+    //扩展方法, weex call Eagle使用, 如果是instance相关的, 那么options里应该有对应的instance id. 并且只call到对应的plugin上, 如果是全局相关的. 那么每个plugin都被call到.
+    //   bool返回值代表switch分支是否包含当前task.
+    virtual bool CallEagleTaskFromWeex(const char* instanceId, const char* task, const char* options) = 0;
+  };
+
+  static EagleBridge* GetInstance();
+
+  //WeexCore调用这个方法来创建PluginPage.  如果没有对应的Plugin则内部调用ReportException.
+  //Call In JSThread
+  void CreatePage(const char* plugin_type, const char* instanceId, const char* func,
+                  const char* script, int script_length,
+                  const char* opts,
+                  const char* initData,
+                  const char* extendsApi, std::function<void(const char*, const char*)> function);
+
+  //Call In JSThread
+  EagleModeReturn DestroyPage(const char* instanceId);
+
+  //Call In JSThread
+  EagleModeReturn RefreshPage(const char* instanceId, const char* init_data);
+
+  //Call In JSThread
+  void UpdateComponentData(const char* instanceId,
+                           const char* cid,
+                           const char* json_data);
+
+  //Call In JSThread
+  bool CallEagleTaskFromWeex(const char* instanceId, const char* task, const char* options);
+
+  //注册plugin.
+  void set_data_render_handler(const std::string& plugin_type,
+                               DataRenderHandler* data_render_handler);
+
+  DataRenderHandler* get_data_render_handler(const std::string& plugin_type);
+
+  inline WeexCoreHandler* weex_core_handler() const { return weex_core_handler_.get(); };
+
+
+ private:
+  EagleBridge();
+
+  //支持多plugin. CreatePage时候根据plugin_type确定.
+  //Call In JSThread
+  DataRenderHandler* data_render_handler(const std::string& instance_id) const;
+
+  static EagleBridge* g_instance;
 
+  std::unique_ptr<WeexCoreHandler> weex_core_handler_;
+  std::map<std::string, DataRenderHandler*> plugins_;
+  std::map<std::string, DataRenderHandler*> pages_;
+  std::mutex plugin_mutex_;
+};
 }
 
 #endif
diff --git a/weex_core/Source/core/bridge/eagle_bridge_ext.cpp b/weex_core/Source/core/bridge/eagle_bridge_ext.cpp
new file mode 100644
index 0000000..671d140
--- /dev/null
+++ b/weex_core/Source/core/bridge/eagle_bridge_ext.cpp
@@ -0,0 +1,112 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include "core/bridge/eagle_bridge_ext.h"
+#include "third_party/json11/json11.hpp"
+#include "core/manager/weex_core_manager.h"
+
+#ifdef OS_ANDROID
+#include "wson/wson.h"
+#include "android/utils/params_utils.h"
+#include "base/string_util.h"
+#endif
+namespace WeexCore {
+namespace EagleExt{
+
+std::function<void(const char*, const char*)> CreatePageDownloadExec(const char* instanceId,
+                                         const char* func,
+                                         const char* script,
+                                         int script_length,
+                                         const char* opts,
+                                         const char* initData,
+                                         const char* extendsApi){
+  std::function<void(const char*, const char*)> exec_js =
+      [instanceId = std::string(instanceId), func = std::string(func),
+          opts = std::string(opts), initData = std::string(initData),
+          extendsApi = std::string(extendsApi)](const char* result, const char* bundleType) {
+        std::string error;
+        auto opts_json = json11::Json::parse(opts, error);
+        std::map<std::string, json11::Json>& opts_map =
+            const_cast<std::map<std::string, json11::Json>&>(
+                opts_json.object_items());
+        opts_map["bundleType"] = bundleType;
+        std::vector<INIT_FRAMEWORK_PARAMS*> params;
+        auto bridge =         WeexCoreManager::Instance()
+                                  ->script_bridge()
+                                  ->script_side();
+        if(!bridge){
+            return;
+        }
+        bridge->CreateInstance(instanceId.c_str(), func.c_str(), result,
+                             opts_json.dump().c_str(), initData.c_str(),
+                             strcmp("Rax", bundleType) ? "\0" : extendsApi.c_str(),
+                             params);
+      };
+  return exec_js;
+}
+#ifdef OS_ANDROID
+void RefreshPageEagle(const char* page_id, const char* init_data) {
+  std::vector<VALUE_WITH_TYPE*> msg;
+
+  VALUE_WITH_TYPE* event = getValueWithTypePtr();
+  event->type = ParamsType::BYTEARRAY;
+  auto buffer = wson_buffer_new();
+  wson_push_type_uint8_string(
+      buffer, reinterpret_cast<const uint8_t*>(page_id), strlen(page_id));
+  event->value.byteArray = genWeexByteArray(
+      static_cast<const char*>(buffer->data), buffer->position);
+  wson_buffer_free(buffer);
+  msg.push_back(event);
+
+  // args -> { method: 'fireEvent', args: [ref, "nodeEvent", args , domChanges, {params: [ {"templateId": templateId, "componentId": id, "type": type, "params" : [...]} ]}] }
+  VALUE_WITH_TYPE* args = getValueWithTypePtr();
+  args->type = ParamsType::JSONSTRING;
+  json11::Json final_json = json11::Json::array{
+      json11::Json::object{
+          {"method", "fireEvent"},
+          {"args",
+                     json11::Json::array{
+                         "", "refresh", json11::Json::array{}, "",
+                         json11::Json::object{
+                             {"params",
+                                 json11::Json::array{
+                                     json11::Json::object{
+                                         {"data", init_data}
+                                     }
+                                 }}
+                         }
+                     }}
+      }
+  };
+  std::string out = final_json.dump();
+  auto utf16_key = weex::base::to_utf16(const_cast<char*>(out.c_str()),
+                                        out.length());
+  args->value.string = genWeexString(
+      reinterpret_cast<const uint16_t*>(utf16_key.c_str()), utf16_key.size());
+  msg.push_back(args);
+  auto bridge = WeexCore::WeexCoreManager::Instance()->script_bridge()->script_side();
+  if (!bridge){
+    return;
+  }
+  bridge->ExecJS(
+      page_id, "", "callJS", msg);
+  freeParams(msg);
+}
+#endif
+}
+}
\ No newline at end of file
diff --git a/weex_core/Source/core/bridge/eagle_bridge_ext.h b/weex_core/Source/core/bridge/eagle_bridge_ext.h
new file mode 100644
index 0000000..c361cd6
--- /dev/null
+++ b/weex_core/Source/core/bridge/eagle_bridge_ext.h
@@ -0,0 +1,52 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef CORE_BRIDGE_EAGLE_BRIDGE_EXT_H
+#define CORE_BRIDGE_EAGLE_BRIDGE_EXT_H
+
+#if defined __cplusplus
+
+#include <string>
+#include <map>
+#include <functional>
+#include <set>
+#include <mutex>
+
+namespace WeexCore {
+namespace EagleExt {
+
+//this must stay in weex because weex_core_manager.h has inline static which can't be compiled into Eagle so.
+
+std::function<void(const char*, const char*)> CreatePageDownloadExec(const char* instanceId,
+                                         const char* func,
+                                         const char* script,
+                                         int script_length,
+                                         const char* opts,
+                                         const char* initData,
+                                         const char* extendsApi);
+
+#ifdef OS_ANDROID
+void RefreshPageEagle(const char* page_id, const char* init_data);
+#endif
+
+}
+}
+
+#endif
+#endif
diff --git a/weex_core/Source/core/bridge/platform/core_side_in_platform.cpp b/weex_core/Source/core/bridge/platform/core_side_in_platform.cpp
index 192b9bf..435f356 100644
--- a/weex_core/Source/core/bridge/platform/core_side_in_platform.cpp
+++ b/weex_core/Source/core/bridge/platform/core_side_in_platform.cpp
@@ -356,54 +356,13 @@ int CoreSideInPlatform::RefreshInstance(
 
   std::string init_data = weex::base::to_utf8(params[1]->value.string->content,
                                               params[1]->value.string->length);
-  auto handler = EagleBridge::GetInstance()->data_render_handler();
-  if (handler && handler->RefreshPage(instanceId, init_data)) {
-    std::vector<VALUE_WITH_TYPE*> msg;
-
-    VALUE_WITH_TYPE* event = getValueWithTypePtr();
-    event->type = ParamsType::BYTEARRAY;
-    auto buffer = wson_buffer_new();
-    wson_push_type_uint8_string(
-        buffer, reinterpret_cast<const uint8_t*>(instanceId), strlen(instanceId));
-    event->value.byteArray = genWeexByteArray(
-        static_cast<const char*>(buffer->data), buffer->position);
-    wson_buffer_free(buffer);
-    msg.push_back(event);
-
-    // args -> { method: 'fireEvent', args: [ref, "nodeEvent", args , domChanges, {params: [ {"templateId": templateId, "componentId": id, "type": type, "params" : [...]} ]}] }
-    VALUE_WITH_TYPE* args = getValueWithTypePtr();
-    args->type = ParamsType::JSONSTRING;
-    json11::Json final_json = json11::Json::array{
-        json11::Json::object{
-            {"method", "fireEvent"},
-            {"args",
-             json11::Json::array{
-                 "", "refresh", json11::Json::array{}, "",
-                 json11::Json::object{
-                     {"params",
-                      json11::Json::array{
-                          json11::Json::object{
-                              {"data", init_data}
-                          }
-                      }}
-                 }
-             }}
-        }
-    };
-    std::string out = final_json.dump();
-    auto utf16_key = weex::base::to_utf16(const_cast<char*>(out.c_str()),
-                                          out.length());
-    args->value.string = genWeexString(
-        reinterpret_cast<const uint16_t*>(utf16_key.c_str()), utf16_key.size());
-    msg.push_back(args);
-    ScriptBridge* bridge = WeexCore::WeexCoreManager::Instance()->script_bridge();
-    if (!bridge){
-      return false;
-    }
-    bridge->script_side()->ExecJS(
-        instanceId, "", "callJS", msg);
-    freeParams(msg);
+
+  EagleModeReturn mode = EagleBridge::GetInstance()->RefreshPage(instanceId, init_data.c_str());
+  if (mode == EagleModeReturn::EAGLE_ONLY){
     return true;
+  } else {
+    //mode == EagleModeReturn::EAGLE_AND_SCRIPT || mode == EagleModeReturn::NOT_EAGLE
+    //continue;
   }
   return ExecJS(instanceId, nameSpace, func, params);
 #else
@@ -505,86 +464,14 @@ int CoreSideInPlatform::CreateInstance(const char *instanceId, const char *func,
                                        const char *initData,
                                        const char *extendsApi, std::vector<INIT_FRAMEWORK_PARAMS*>& params,
                                        const char *render_strategy) {
-
-  // First check about DATA_RENDER mode
   if (render_strategy != nullptr) {
-    std::function<void(const char *, const char *)> exec_js =
-        [instanceId = std::string(instanceId), func = std::string(func),
-         opts = std::string(opts), initData = std::string(initData),
-         extendsApi = std::string(extendsApi)](const char *result, const char *bundleType) {
-          std::string error;
-          auto opts_json = json11::Json::parse(opts, error);
-          std::map<std::string, json11::Json> &opts_map =
-              const_cast<std::map<std::string, json11::Json> &>(
-                  opts_json.object_items());
-          opts_map["bundleType"] = bundleType;
-          std::vector<INIT_FRAMEWORK_PARAMS*> params;
-          WeexCoreManager::Instance()
-              ->script_bridge()
-              ->script_side()
-              ->CreateInstance(instanceId.c_str(), func.c_str(), result,
-                               opts_json.dump().c_str(), initData.c_str(),
-                               strcmp("Rax", bundleType) ? "\0" : extendsApi.c_str(),
-                               params);
-        };
-    if (strcmp(render_strategy, "DATA_RENDER") == 0) {
-        auto handler = EagleBridge::GetInstance()->data_render_handler();
-        if(handler){
-          handler->CreatePage(script, instanceId, render_strategy, initData, exec_js);
-        }
-        else{
-          WeexCore::WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->ReportException(
-            instanceId, "CreatePageWithContent", 
-            "There is no data_render_handler when createInstance with DATA_RENDER mode");
-        }
-
-      return true;
-    } else if (strcmp(render_strategy, "DATA_RENDER_BINARY") == 0) {
-      std::string error;
-      std::string env_str;
-      std::string option = "{}";
-      auto opts_json_value = json11::Json::parse(opts, error);
-      if (error.empty()) {
-        auto env_obj = opts_json_value["env"];
-        auto bundleUrl = opts_json_value["bundleUrl"];
-        env_str = "";
-        if (env_obj.is_object()) {
-          const json11::Json& options = env_obj["options"];
-          const json11::Json::object& options_obj = options.object_items();
-          json11::Json::object new_env{
-              env_obj.object_items()
-          };
-          for(auto &it :options_obj){
-            new_env[it.first] = it.second;
-          }
-          env_str = json11::Json(new_env).dump();
-        }
-
-        json11::Json::object new_option{
-            {"bundleUrl", bundleUrl},
-            {"weex", json11::Json::object{
-                {"config",opts_json_value}
-            }}
-        };
-        option = json11::Json(new_option).dump();
-      }
-      
-      auto handler = EagleBridge::GetInstance()->data_render_handler();
-      if(handler){
-        handler->CreatePage(script, static_cast<size_t>(script_length), instanceId, option, env_str, initData, exec_js);
-      }
-      else{
-        WeexCore::WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->ReportException(
-          instanceId, "CreatePageWithContent", 
-          "There is no data_render_handler when createInstance with DATA_RENDER_BINARY mode");
-      }
+    if(strcmp(render_strategy, "JSON_RENDER") == 0){
+      JsonRenderManager::GetInstance()->CreatePage(script, instanceId, render_strategy);
       return true;
     }
 
-    if(strcmp(render_strategy, "JSON_RENDER") == 0){
-       JsonRenderManager::GetInstance()->CreatePage(script, instanceId, render_strategy);
-       return true;
-    }
+    EagleBridge::GetInstance()->CreatePage(render_strategy, instanceId, func, script, script_length, opts, initData ,extendsApi, 0);
+    return true;
   }
 
 
@@ -603,13 +490,16 @@ std::unique_ptr<WeexJSResult> CoreSideInPlatform::ExecJSOnInstance(const char *i
 }
 
 int CoreSideInPlatform::DestroyInstance(const char *instanceId) {
-    auto handler = EagleBridge::GetInstance()->data_render_handler();
-    if (handler != nullptr) {
-      handler->DestroyInstance(instanceId);
-    }
     if (JsonRenderManager::GetInstance()->ClosePage(instanceId)) {
       return true;
     }
+    EagleModeReturn mode = EagleBridge::GetInstance()->DestroyPage(instanceId);
+    if (mode == EagleModeReturn::EAGLE_ONLY){
+      return true;
+    } else {
+      //mode == EagleModeReturn::EAGLE_AND_SCRIPT || mode == EagleModeReturn::NOT_EAGLE
+      //continue;
+    }
     auto script_side = WeexCoreManager::Instance()->script_bridge()->script_side();
     if (script_side) {
         return script_side->DestroyInstance(instanceId);
diff --git a/weex_core/Source/core/bridge/script/core_side_in_script.cpp b/weex_core/Source/core/bridge/script/core_side_in_script.cpp
index d833da9..09d21e4 100644
--- a/weex_core/Source/core/bridge/script/core_side_in_script.cpp
+++ b/weex_core/Source/core/bridge/script/core_side_in_script.cpp
@@ -451,15 +451,7 @@ void CoreSideInScript::OnReceivedResult(long callback_id,
 void CoreSideInScript::UpdateComponentData(const char* page_id,
                                            const char* cid,
                                            const char* json_data) {
-    auto handler = EagleBridge::GetInstance()->data_render_handler();
-    if(handler){
-      handler->UpdateComponentData(page_id, cid, json_data);
-    }
-    else{
-      WeexCore::WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->ReportException(
-        page_id, "UpdateComponentData", 
-        "There is no data_render_handler when UpdateComponentData invoked");
-    }
+  EagleBridge::GetInstance()->UpdateComponentData(page_id, cid, json_data);
 }
 
 bool CoreSideInScript::Log(int level, const char *tag,