Files
2023-11-03 13:31:48 +00:00

29 KiB
Raw Permalink Blame History

Debug


Hippy Debugging Principles

Hippy runs directly in real device's JS engine, using WebSocket on Android to communicate with Chrome on the computer via Chrome DevTools Protocol debugging, while iOS uses the built-in JavaScriptCore to connect with Safari for debugging, and in the newer Hippy versions of iOS, it can also be debugged using Chrome DevTools.

The JS code running in Hippy can originate from a local file, or from a remote server.

The @hippy/debug-server-next is aimed to solve the problem of getting the JS file for debugging in native debug mode, and send the Chrome DevTools Protocol back to the debugger.

Project Initialization

  1. run git clone https://github.com/Tencent/Hippy.git

    ! > Hippy repository uses git-lfs to manage so, gz, otf, png, jpg files, please make sure you have git-lfs installed.

  2. Run the command npm install at project root to install front-end dependencies.

  3. Run the command npx lerna bootstrap at project root to install each package dependency of the front-end. (Hippy uses Lerna to manage multiple JS repositories, if lerna command is not found, first execute npm install lerna -g)

  4. Run the command npm run build at project root to compile the front-end SDK package.

  5. Select a front-end sample project to compile, run npm run buildexample -- [hippy-react-demo|hippy-vue-demo] in project root.

Native Environment Preparation

We recommend leaving a backdoor in the native code to enter debug mode after being triggered by certain conditions, the specific code can be found in iOS and Android, where a TestModule is implemented and the front-end enters debug mode when its debug or remoteDebug methods are called. The native can be accessed by other means. The native opens the Hippy Debug page with the following code.

  1. Android.

         // Initialize the hippy engine
         HippyEngine.EngineInitParams initParams = new HippyEngine.EngineInitParams();
         // optional: whether to set to debug mode, default DebugMode.None. set DebugMode.Dev for debug mode, all jsbundle are downloaded from the debug server
         initParams.debugMode = HippyEngine.DebugMode.Dev; // debugMode still uses boolean type below 2.16.0 versions  => initParams.debugMode = true;
         initParams.debugServerHost = "localhost:38989";
         initParams.debugBundleName = "index.bundle";
    
  2. iOS.

    - (void)viewDidLoad {
        // Enable debugging
        NSDictionary *launchOptions = @{@"DebugMode": @(YES)};
        // Use the default http://localhost:38989/index.bundle
        NSString *bundleStr = [HippyBundleURLProvider sharedInstance].bundleURLString;
        NSURL *bundleUrl = [NSURL URLWithString:bundleStr];
        HippyBridge *bridge = [[HippyBridge alloc] initWithDelegate:self
                                                          bundleURL:bundleUrl
                                                     moduleProvider:nil
                                                      launchOptions:launchOptions
                                                        executorKey:@"Demo"];
    }
    
    
    - (BOOL)shouldStartInspector:(HippyBridge *)bridge {
        return bridge.debugMode;
    }
    
    - (NSURL *)inspectorSourceURLForBridge:(HippyBridge *)bridge {
        return bridge.bundleURL;
    }
    

Front-end Environment Preparation

  1. install the next generation of debugging tools: npm i -D @hippy/debug-server-next@latest

  2. Modify the Webpack configuration to add the debug service address, the default is http://localhost:38989

    module.exports = {
      devServer: {
        // debug service address
        remote: {
          protocol: 'http',
          // Local LAN IP for real iOS device debugging
          // localhost for iOS emulator and real Android device debugging
          // configured as remote server IP or domain name for remote debugging
          host: '192.168.1.100',
          // debug service port
          port: 38989,
        },
        // default false, set to true debugging service supports multiple projects debugging at the same time without interfering with each other
        multiple: false,
        // default false, hippy vue projects can be manually enabled
        vueDevtools: false,
        // default hot/liveReload both true, if you only want to use live-reload function, please set hot to false and liveReload to true
        hot: true,
        liveReload: true,
        client: {
          overlay: false,
        },
      },
      // ... other config
    }
    
  3. Modify the start build command in package.json. If the business is started with a custom cli, refer to package build API for configuration

    {
      "scripts": {
         // -c or --config provides the webpack config path
         "hippy:dev": "node ./scripts/env-polyfill.js hippy-dev -c ./scripts/hippy-webpack.dev.js"
      }  
    } 
    
  4. Run npm run hippy:dev to start building and turn on the Dev Server for HMR and Live-Reload as needed, and print out the bundleUrl and debug home address when the build is finished

    hippy dev output
  5. paste bundleUrl and click start button

    iOS remote debug config
  6. Start debugging with the debugger

    • Safari DevTools: Open Safari's development menu on a Mac (Preferences -> Advanced -> Show Development Menu) and follow the instructions below to start debugging. The Safari debugger supports iOS devices and supports HMR & Live-Reload, Log, Sources, Memory and other capabilities.

      Safari Debugger
    • Chrome DevTools: Visit the debug home address printed in step 4 to start debugging. Chrome debugger supports Android & iOS devices with HMR & Live-Reload, Elements, Log, Sources, Memory capabilities.

      Chrome 调试器

    If you don't use our debug homepage, you can also actively open DevTools at chrome://inspect by first making sure that the Discover USB devices checkbox is unchecked, then making sure that Discover network targets is checked, and that the Configure button popup contains the localhost:38989 debug service address, and the words Hippy debug tools for V8 should appear in the Remote Target below, click the inspect link below to open the Chrome debugger.

    Chrome inspect

@hippy/debug-server-next contains all the capabilities of @hippy/debug-server, a debugging tool for Hippy 3.0 that is fully backward compatible.

Debugging Javascript

Although Hippy is a front-end framework, it still runs in the native. If the native provides a backdoor to directly link to the debugging service, you can directly use the native backdoor to connect to the native for debugging.

Here, take the official example to describe how to debug.

!> Note that the official example makes @hippy/react and @hippy/vue an alias to the packages directory. In order to debug the official example, you need to first use npm run build in the Hippy project root to compile the front-end SDK; or remove the alias to packages in example's scripts directory.

iOS

iOS debugging supports both emulator and real iOS device. Since JSBundle and debugging protocols depend on network transfer, you need to make sure your device is on the same LAN as the development machine when debugging on real device. Therefore, we recommend using the emulator.

Emulator Debugging

  1. Click Xcode on Mac AppStore to download and install Xcode.
  2. use Xcode to open HippyDemo.xcodeproj project file in Hippy iOS example project, and click run. Under normal circumstances, you should be able to start simulator and run the built-in Hippy front-end code,
  3. open project hippy-react-demo or hippy-vue-demo underexamples. after installing the dependencies via npm i, use npm run hippy:dev to start building and debugging,
  4. Go back to the simulator, paste bundleUrl and start debugging
  5. If HMR or Live-Reload is enabled when the JS source file is changed, it will be refreshed automatically after compilation; otherwise, you need to press Command + R or Command + D to bring up the Reload panel to refresh it.

If Command + D cannot bring up the panel, you can click Device -> Shake to force open the Reload panel

Real iOS device debugging

  1. Real iOS device debugging only supports XCode compiled apps, and the JavaScript debugging and web inspector options need to be enabled on iOS devices

    Safari debug settings
  2. Make sure the iOS device and debug service are on the same LAN

  3. Compile App,paste bundleUrl and start debugging

!> Note: You must ensure that the development machine and the device are on the same LAN when debugging on the real device, otherwise the JSBundle will fail to load. Neither of the following is satisfied:
  (a) The development machine and the real iOS device are connected to different network environments.
  (b) The development machine is connected to the network cable and the mobile device is connected to WiFi.

Android

Android uses the adb port mapping feature to solve the communication problem between the real Android device and the development machine, but because of the efficiency of the ARM simulator, it is more recommended to use the real device for debugging.

Specific procedure:

  1. Download and install Android Studio
  2. Using Android Studio to open Hippy Repo root directory, which will load Hippy Android example project.
  3. Plug in your real Android device via the data cable and click Run in Android Studio. Normally, the device should already be running the Hippy Demo app.
  4. Go back to your device and make sure that USB debug mode is turned on - you can enter Developer mode' by clicking Build in succession on the About page, and then turn on USB debug mode after you enter the Developer mode screen.
  5. Run adb reverse --remove-all && adb reverse tcp:38989 tcp:38989 to make sure port 38389 is not occupied.
  6. Open the front-end example project hippy-react-demo or hippy-vue-demo, use npm run hippy:dev to start building and debugging service.
  7. Back to your device, paste bundleUrl and start debugging
  8. If HMR or Live-Reload is enabled when the JS source file is changed, it will be refreshed automatically after compilation; otherwise, you need to press Command + R or Command + D to bring up the Reload panel.

Elements Visualization Inspection

Android SDK min support version 2.9.0 iOS SDK min support version 2.11.5

Hippy implements node and property mapping from front-end to native, allowing visual inspection of Elements on Chrome DevTools.



Operate Mobile Phone Interface

Android SDK min supported version 2.16.0

Hippy implements the Input interface of the Chrome DevTools Protocol . You can directly operate the mobile phone interface on Chrome DevTools without switching back and forth during debugging.

HMR & Live-Reload

min support version 2.12.0

hippy-react-demo config script

hippy-vue-demo config script

HMR preview

!> Please don't import HMR-related configuration in production environment.

After the developer has modified the front-end code, we can refresh the component view by Hot Module Replacement (HMR) retaining state, or reload the business instance by live-reload, as follows.

Hippy-Vue

  1. Install live-reload dependencies

    npm i @hippy/vue@^2.12.0
    npm i -D @hippy/debug-server-next@latest @hippy/vue-loader @hippy/vue-css-loader
    
  2. Webpack config demo

    const VueLoaderPlugin = require('@hippy/vue-loader/lib/plugin');
    const vueLoader = '@hippy/vue-loader';
    
    module.exports = {
     devServer: {
       // default hot/liveReload set to true. If you only want to use live-reload, set hot to false and liveReload to true
       hot: true,
       liveReload: true,
       client: {
         // Error masks are not supported at the moment
         overlay: false,
       },
     },
     plugins: [
       new VueLoaderPlugin(),
       // add other plugin ...
     ],
     module: {
       rules: [
         {
           test: /\.vue$/,
           use: [
             vueLoader,
           ],
         },
       ],
       // add other loaders ...
     }
    }
    
  3. package.json configuration.

    {
      "scripts": {
          // -c or --config provides webpack config path
         "hippy:dev": "node ./scripts/env-polyfill.js hippy-dev -c ./scripts/hippy-webpack.dev.js"     }  
    } 
    
  4. start development: npm run hippy:dev

  5. If the Android device is disconnected, you need to manually forward the port with adb: adb reverse tcp:38989 tcp:38989.

  6. iOS hot update: iOS devices need to be proxied to the development machine or on the same network segment to use the HMR capability. Webpack configuration is modified as shown below, for the emulator, which is on the same network segment as the development machine, the IP is accessible by setting to localhost.

    module.exports = {
      devServer: {
        host: '<your_ip_or_localhost_with_proxy>',
      },
    }
    

Hippy-React

  1. install HMR

    npm i @hippy/react@^2.12.0
    npm i -D @hippy/debug-server-next@latest @hippy/hippy-react-refresh-webpack-plugin react-refresh
    
  2. Webpack configuration example

    const ReactRefreshWebpackPlugin = require('@hippy/hippy-react-refresh-webpack-plugin');
    
    module.exports = {
      devServer: {
        // default hot, liveReload are true, if you only want to use live-reload function, please set hot to false and liveReload to true
        hot: true,
        liveReload: true,
        client: {
          // Error masks are not supported at the moment
          overlay: false,
        },
      },
      plugins: [
        new ReactRefreshWebpackPlugin({
          // Error masks are not supported at this time
          overlay: false,
        }),
      ],
      module: {
        rules: [
          {
            test: /\.(jsx?)$/,
            use: [
              {
                loader: 'babel-loader',
                options: {
                  sourceType: 'unambiguous',
                  presets: [
                   '@babel/preset-react',
                   [
                     '@babel/preset-env',
                     {
                       targets: {
                         chrome: 57,
                         ios: 9,
                       },
                     },
                   ],
                  ],
                  plugins: [
                    ['@babel/plugin-proposal-class-properties'],
                    ['@babel/plugin-proposal-decorators', { legacy: true }],
                    ['@babel/plugin-transform-runtime', { regenerator: true }],
                    // add react-refresh babel plugin
                    require.resolve('react-refresh/babel'),
                  ],
                },
              },
            ],
          },
        // other loader ...
        ],
      },
    };
    
  3. package.json configuration.

    {
       "scripts": {
         // -c or --config provide Webpack config path
         "hippy:dev": "node ./scripts/env-polyfill.js hippy-dev -c ./scripts/hippy-webpack.dev.js"
       }
    }
    
  4. Run the npm run hippy:dev commands.

  5. If the Android device is disconnected, you need to manually forward the port with adb: adb reverse tcp:38989 tcp:38989.

  6. iOS hot update: iOS devices need to be proxied to the development machine or on the same network segment to use the HMR capability. Webpack configuration is modified as shown below, for the emulator, which is on the same network segment as the development machine, the IP is accessible by writing localhost.

    module.exports = {
      devServer: {
        host: '<your_ip_or_localhost_with_proxy>',
      },
    }
    

Vue Devtools

Minimum supported version 2.13.7

Support for debugging Vue component trees, component state, routes, store, and event performance

  1. install vue-devtools dependencies.

    npm i @hippy/vue@^2.13.7 @hippy/vue-router@^2.13.7
    npm i @hippy/debug-server-next@latest -D
    
  2. open vue devtools

    module.exports = {
     devServer: {
        remote: {
          protocol: 'https',
          host: 'devtools.qq.com',
          port: 443,
        },
       // default is false, when enabled, vue debugging commands will be distributed via the remote debugging service specified in the remote field
       vueDevtools: true
     },
    

! > Vue Devtools configuration will inject debugging code at runtime, which may have some performance impact, please do not introduce it in the production environment.

React Devtools

Min support client version 2.13.7
Min support front-end version 2.14.0

Support for debugging React component tree, component state, route, performance, etc.

Configuration

  1. Install react devtools dependencies:

    npm i @hippy/react@^2.14.0
    npm i @hippy/debug-server-next@latest -D
    
  2. Open react devtools

    module.exports = {
     devServer: {
        remote: {
          protocol: 'https',
          host: 'devtools.qq.com',
          port: 443,
        },
       // default false, which will distribute react debugging commands through the remote debugging service specified by the `remote` field.
       reactDevtools: true
     },
     module: {
       rules: [
         {
           test: /\. (jsx?)$/,
           // must add the following line. to make babel ignore react-devtools plugin
           exclude: /@hippy\/hippy-react-devtools-plugin/,
           use: [
             {
               loader: 'babel-loader',
               options: {
                 sourceType: 'unambiguous',
                 presets: [
                   '@babel/preset-react',
                   [
                     '@babel/preset-env',
                     {
                       targets: {
                         chrome: 57,
                         ios: 9,
                       },
                     },
                   ],
                 ],
                 plugins: [
                   ['@babel/plugin-proposal-class-properties'],
                   ['@babel/plugin-proposal-decorators', { legacy: true }],
                   ['@babel/plugin-transform-runtime', { regenerator: true }],
                   require.resolve('react-refresh/babel'),
                 ],
               },
             },
           ],
         },
       ],
     },
    }
    

!> React Devtools configuration injects debugging code at runtime, which may have some performance impact, please do not introduce it in production environment.

Translated with www.DeepL.com/Translator (free version)

Build & Compile API

@hippy/debug-server-next provides command hippy-debug and hippy-dev to debug and compile. In addition, it provides interface for custom CLI tools to call.:

const { webpack } = require('@hippy/debug-server-next');

// start webpack compiling, supports HMR and other ability
webpack(webpackConfig, (err, stats) => {
  // handle webpack callbacks
});

Remote Debugging

Remote Debugging currently supports two modes, including Development Remote Debugging and Production Remote Debugging mode

  • Development Remote Debugging mode needs to load bundle from remote server for debug
  • Production Remote Debugging mode uses local cached bundle instead of remote, which is more suitable for production environment. If no such requirement, you can also use the above Development Remote Debugging mode

Development Remote Debugging

Local debugging has two pain points.

  1. unable to cover all models and difficult in locating problems from user feedback.
  2. unable to get rid of the data cable.

Then we can consider using remote debugging for these scenarios, with the following preview.

Front-end Usage Configuration

  1. Install the next generation debugging tool: npm i -D @hippy/debug-server-next@latest.

  2. Modify the Webpack configuration and add remote field to configure the compilation product upload address and debug service address (default http://127.0.0.1:38989). For security reasons, the official remote debugging service is not available on the public network, you need to deploy it privately by yourself.

    module.exports = {
      devServer: {
        // The remote debug address, configured as the address of your private debug service
        remote: {
          protocol: 'https',
          host: 'devtools.qq.com',
          port: 443,
          // Configure the scheme for the host app to scan and load, if you don't need to scan, you may not configure it
          qrcode: (bundleUrl) => {
            // must specify business bundleName
            const bundleName = 'QQGroupGameRank';
            return `mqqapi://hippy/remoteDebug?bundleName=${bundleName}&bundleUrl=${encodeURIComponent(bundleUrl)}`;
          }
        },
        client: {
          overlay: false,
        },
      },
      // other config ...
    }
    

    !> Configure that the compilation product will be uploaded to the remote end when debugging remotely and deleted after debugging is finished. As a precaution, make sure that the code does not contain sensitive information (e.g. keys, etc.).

    !> When debugging remotely, publicPath will be set to {protocol}://${host}:${port}/<hash>/ to distinguish between different business.

    !> when business loads remote js sub-bundles, if customChunkPath is not configured, the address of publicPath will be used by default, please make sure the remote subpackage is also uploaded to the debug server at the same time.

  3. Start the build: npm run hippy:dev, and the debug message will be printed when the build is finished:

    where the three printed fields are:

    • bundleUrl: the address of the JSBundle for remote debugging, filled in the remoteServerUrl field of the host App
    • debug page: the debugging home page of the PC side
    • bundleUrl scheme: scheme of the host App's code scanning

Host App Configuration

Set Host App debugMode to true and pass in the bundleUrl generated by front-end Webpack for remote wireless debugging, we recommend the host to use input box or scan QR code to pass in.

  1. Android

     // initialize hippy engine
     HippyEngine.EngineInitParams initParams = new HippyEngine.EngineInitParams();
     initParams.debugMode = HippyEngine.DebugMode.Dev; // debugMode still uses boolean type below 2.16.0 versions  => initParams.debugMode = true;
     initParams.remoteServerUrl = ""; // remote debug bundleUrl
    
  2. iOS

    - (void)viewDidLoad {
        // Enable debugging
        NSDictionary *launchOptions = @{@"DebugMode": @(YES)};
        NSString *bundleStr = ""; // remote debug bundleUrl
        NSURL *bundleUrl = [NSURL URLWithString:bundleStr];
        HippyBridge *bridge = [[HippyBridge alloc] initWithDelegate:self
                                                          bundleURL:bundleUrl
                                                     moduleProvider:nil
                                                      launchOptions:launchOptions
                                                        executorKey:@"Demo"];
    }
    
    - (BOOL)shouldStartInspector:(HippyBridge *)bridge {
        return bridge.debugMode;
    }
    
    - (NSURL *)inspectorSourceURLForBridge:(HippyBridge *)bridge {
        return bridge.bundleURL;
    }
    

Production Remote Debugging

In the production environment, developers can directly debug the local bundle, restore the scene of online users, and improve the efficiency for fixing problem

Front-end Usage

no need

Host App

  1. Android:

Minimum supported version 2.16.0

The type of debugMode is changed from boolean type to enumeration type

  public enum DebugMode {
    None, // Production
    Dev, // Development
    UserLocal, // directly use local bundle to debug instead of from remote server
  }

Step One:

// hippy engine initialized
  HippyEngine.EngineInitParams initParams = new HippyEngine.EngineInitParams();
  initParams.debugMode = HippyEngine.DebugMode.UserLocal; // open debug in production

Step two:

Sometimes engine startup and business are separated in many business, so we separate the debugging option startup and debug server connection, which is better for usage.

// connect debug server before or after business startup
mHippyEngine.getEngineContext().getBridgeManager().connectDebugUrl("ws://${ip}:${port}/debugger-proxy");
mHippyView = mHippyEngine.loadModule(loadParams, new HippyEngine.ModuleListener() {
    @Override
    public void onLoadCompleted(ModuleLoadStatus statusCode, String msg, HippyRootView hippyRootView) {
      if (statusCode != ModuleLoadStatus.STATUS_OK) {
        LogUtils.e("MyActivity", "loadModule failed code:" + statusCode + ", msg=" + msg);
      }
    }

    @Override
    public boolean onJsException(HippyJsException exception) {
      return true;
    }
});

2.iOS

(coming soon)

List of supported capabilities for remote debugging

min support version 2.13.1

Platform HMR & Live-Reload Elements Log Sources Memory
Android ✅ ✅ ✅ ✅ ✅
iOS ✅ ✅ ❌ ❌ ❌

Framework Log

Both hippy-react and hippy-vue will output the information of communicating with native, including the js-native node operations, events sent/received. These logs are actually very helpful for business debugging, allowing developers to understand how the front-end framework translates code into a syntax that the native can understand. When you encounter problems, please first check the framework communication logs, as they can basically locate most of the problems.

If you need to turn off the logs, you can add silent: true to hippy-react's new Hippy startup parameters, or turn on Vue.config.silent = true; in hippy-vue project entry file, or add silent: true to hippy-vue-next's createApp init options.

Communication Info