Skip to content

Industrial Extension Development Tips

This page covers compatibility issues and best practices when developing extensions for industrial robots.

Environment Limitations

alert and confirm Functions Are Not Available

In the industrial robot extension environment, native alert() , confirm() , and prompt() functions cannot be used.

Problem Description

The WebView environment on teach pendants disables these blocking dialog functions. Calling them directly will result in:

  • alert() - No response or silent failure
  • confirm() - Unable to obtain user confirmation
  • prompt() - Unable to obtain user input

We strongly recommend using UI frameworks (such as Element UI, Ant Design, etc.) or the runtime API directly to implement notifications and dialogs, instead of using the browser's native alert / confirm / prompt functions.

The runtime API provides complete notification and dialog functionality:

Using Runtime API (Recommended):

The way you use runtime APIs depends on your development approach:

  • Traditional Approach (directly including script tags in HTML): Use the global object gbtExtension

    Download the runtime library to your local project using these methods:

    bash
    # Method 1: Install via npm and copy
    pnpm add @agilebot/extension-runtime
    cp ./node_modules/@agilebot/extension-runtime/dist/browser.js ./static/extension-runtime.js
    
    # Method 2: Download directly from unpkg to your project
    curl -o ./static/extension-runtime.js https://unpkg.com/@agilebot/extension-runtime/dist/browser.js
    # Or use wget
    wget -O ./static/extension-runtime.js https://unpkg.com/@agilebot/extension-runtime/dist/browser.js
  • Module-based Approach (using build tools and modular development): Use import syntax

    ts
    import { 
    rtmNotification
    ,
    rtmMessageBox
    } from '@agilebot/extension-runtime';
    // Show notifications
    rtmNotification
    .
    success
    ('Operation successful!');
    rtmNotification
    .
    error
    ('Operation failed');
    rtmNotification
    .
    info
    ('Information message');
    // Show confirmation dialog
    rtmMessageBox
    .
    confirm
    ('Are you sure you want to delete?')
    .
    then
    (() =>
    console
    .
    log
    ('User confirmed'))
    .
    catch
    (() =>
    console
    .
    log
    ('User cancelled'));
    // Get user input
    rtmMessageBox
    .
    prompt
    ('Please enter your name:')
    .
    then
    ((
    result
    ) =>
    console
    .
    log
    ('User input:',
    result
    ))
    .
    catch
    (() =>
    console
    .
    log
    ('User cancelled'));

    Modern build tools (like Vite, Webpack) will automatically bundle dependencies into the final files, no additional handling needed.

For more details on runtime APIs, please refer to Web Extension Runtime Library.

Alternative Solution: Compatibility Wrapper for Native alert/confirm

Use Only When Necessary

Only use the following compatibility wrapper when your project already extensively uses native alert() / confirm() functions and cannot be refactored.

For new projects or projects that can be refactored, please use the recommended runtime API or UI frameworks directly.

If you must maintain compatibility with native alert() / confirm() , you can wrap them with a compatibility layer:

Traditional Approach Compatibility Example:

js
// Check if running in extension environment
const isExtension = gbtExtension.isInExtension();

// Compatibility wrapper for alert
const alertSuccess = !isExtension
  ? alert
  : gbtExtension.rtmNotification.success;

const alertError = !isExtension
  ? alert
  : gbtExtension.rtmNotification.error;

const alertInfo = !isExtension
  ? alert
  : gbtExtension.rtmNotification.info;

// Compatibility wrapper for confirm (async style)
const myConfirm = function(message) {
  if (!isExtension) {
    return Promise.resolve(confirm(message));
  }
  return new Promise((resolve) => {
    gbtExtension.rtmMessageBox.confirm(message)
      .then(() => resolve(true))
      .catch(() => resolve(false));
  });
};

// Usage example
alertSuccess('Operation successful!');

async function deleteItem() {
  const confirmed = await myConfirm('Are you sure you want to delete?');
  if (confirmed) {
    console.log('User confirmed deletion');
  }
}

Module-based Approach Compatibility Example:

ts
import { 
isInExtension
,
rtmNotification
,
rtmMessageBox
} from '@agilebot/extension-runtime';
const
isExtension
=
isInExtension
();
// Compatibility wrapper for alert const
alertSuccess
= !
isExtension
?
alert
:
rtmNotification
.
success
;
const
alertError
= !
isExtension
?
alert
:
rtmNotification
.
error
;
const
alertInfo
= !
isExtension
?
alert
:
rtmNotification
.
info
;
// Compatibility wrapper for confirm (async style) const
myConfirm
= function(
message
: string) {
if (!
isExtension
) {
return
Promise
.
resolve
(
confirm
(
message
));
} return new
Promise
((
resolve
) => {
rtmMessageBox
.
confirm
(
message
)
.
then
(() =>
resolve
(true))
.
catch
(() =>
resolve
(false));
}); };

Important Notes

When using the compatibility wrapper:

  • The confirm replacement is asynchronous (returns a Promise), you must use await or .then() to handle it
  • Native confirm() is synchronous, but the wrapper is async, which may require code structure adjustments
  • alert is replaced with notifications, which have a different visual appearance than native dialogs
  • It's recommended to encapsulate these functions uniformly in your project entry file to avoid code duplication

Code Transpilation Configuration

Why Transpilation Is Needed

Extension frontend pages run in different device WebView environments:

  • Industrial Robots: Since teach pendants run Android systems (like Android 13) whose WebView may not support ES6+ features (like arrow functions, async/await, optional chaining, etc.), transpilation configuration is required to transpile modern JavaScript code to ES5-compatible code.

  • Collaborative Robots: Collaborative robots run newer versions of Android systems, and their WebView has good support for modern JavaScript features, so transpilation is usually not needed.

Tip

If you are developing extensions for industrial robots, you need to configure transpilation according to this document. If you are developing for collaborative robots, you most likely don't need transpilation configuration and can use modern JavaScript syntax directly.

Scenario 1: Using Babel Transpilation (Traditional Approach)

If you use the traditional approach, i.e., not using modern build tools but writing native JavaScript directly, you can use Babel to transpile code.

Configuration Example

Here's a complete package.json configuration example:

package.json
json
{
  "name": "my-extension",
  "private": true,
  "scripts": {
    "build": "babel ./static/script.js --out-file=./static/script-compiled.js"
  },
  "devDependencies": {
    "@babel/cli": "^7.27.0",
    "@babel/core": "^7.26.10",
    "@babel/preset-env": "^7.26.9"
  },
  "babel": {
    "presets": [
      [
        "@babel/preset-env",
        {
          "modules": false,
          "targets": {
            "android": "13",
            "chrome": "80"
          }
        }
      ]
    ]
  }
}

Key Configuration Details

  1. Dependencies:

    • @babel/cli : Babel command-line tool
    • @babel/core : Babel core library
    • @babel/preset-env : Smart preset that automatically transpiles based on target environment
  2. Transpilation Configuration:

    json
    "babel": {
      "presets": [
        [
          "@babel/preset-env",
          {
            "modules": false,
            "targets": {
              "android": "13",
              "chrome": "80"
            }
          }
        ]
      ]
    }
  3. Build Script:

    bash
    pnpm build

    This will transpile ./static/script.js to ./static/script-compiled.js

Usage Example

Suppose you have the following modern JavaScript code:

static/script.js
js
// Using arrow functions and async/await
const fetchData = async () => {
  const response = await fetch('/api/data');
  const data = await response.json();
  return data?.results ?? [];
};

// Using optional chaining and nullish coalescing
const getUserName = (user) => {
  return user?.profile?.name ?? 'Anonymous';
};

After running pnpm build , Babel will transpile it to ES5-compatible code:

static/script-compiled.js
js
// Transpiled code (example)
var fetchData = function fetchData() {
  return regeneratorRuntime.async(function fetchData$(_context) {
    while (1) {
      switch (_context.prev = _context.next) {
        case 0:
          _context.next = 2;
          return regeneratorRuntime.awrap(fetch('/api/data'));
        case 2:
          response = _context.sent;
          // ...
      }
    }
  });
};

Then reference the transpiled file in HTML:

html
<script src="./static/script-compiled.js"></script>

Scenario 2: Using Vite Legacy Plugin (Module-based Approach)

If you use modern build tools like Vite or Webpack, you can use the corresponding Legacy plugin to handle transpilation.

Vite Configuration Example

  1. Install Plugin:

    bash
    pnpm add -D @vitejs/plugin-legacy
  2. Configure vite.config.ts:

    vite.config.ts
    ts
    import { 
    fileURLToPath
    ,
    URL
    } from 'node:url'
    import {
    defineConfig
    } from 'vite'
    import
    vue
    from '@vitejs/plugin-vue'
    import
    legacy
    from '@vitejs/plugin-legacy'
    export default
    defineConfig
    ({
    base
    : './',
    plugins
    : [
    vue
    (),
    legacy
    ({
    targets
    : ['android >= 13', 'chrome >= 80'],
    modernPolyfills
    : true,
    }), ],
    resolve
    : {
    alias
    : {
    '@':
    fileURLToPath
    (new
    URL
    ('./src', import.meta.
    url
    ))
    }, }, })
  3. Build Project:

    bash
    pnpm build

What the Legacy Plugin Does

@vitejs/plugin-legacy automatically handles the following:

  1. Generates two versions of code:

    • Modern version (ES modules, for new browsers)
    • Legacy version (ES5, for old browsers)
  2. Injects polyfills (like Promise, Array.from, etc.)

  3. Automatically loads the appropriate version based on browser capabilities

After building, Vite generates HTML like this:

html
<!-- Modern browser loading -->
<script type="module" src="./assets/index-abc123.js"></script>

<!-- Old browser loading -->
<script nomodule src="./assets/legacy-polyfills-def456.js"></script>
<script nomodule src="./assets/index-legacy-ghi789.js"></script>

Other Build Tools

Webpack Configuration Example

If using Webpack, you can configure via babel-loader :

webpack.config.js
js
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env', {
                targets: {
                  android: '13',
                  chrome: '80'
                }
              }]
            ]
          }
        }
      }
    ]
  }
};

Verifying Transpilation Results

After building, it's recommended to test on an teach pendant:

  1. Install the extension on the target device
  2. Open the extension page
  3. Verify that all features work correctly