Frontend Development 13 min read

How iMove Enables Seamless In-Browser Code Execution for Developers

iMove, a reusable, function‑oriented JavaScript library, adds right‑click online code execution to its visual workflow, eliminating installation, simplifying testing with mock inputs, handling ES module imports via native browser support, CDN transforms, dynamic imports, and custom events to deliver instant, visual results.

Taobao Frontend Technology
Taobao Frontend Technology
Taobao Frontend Technology
How iMove Enables Seamless In-Browser Code Execution for Developers

iMove is a reusable, function‑oriented, visual‑workflow JavaScript library. For developers, iMove lets you write node functions, export the code, and use it directly in a project, making development convenient.

The online code‑execution feature was added to let users right‑click a node and run its code instantly, reducing installation steps and improving the user experience.

Prelude

A teammate asked how to test newly written node code. The steps were:

Install

@imove/cli

.

Run

imove -d

in the project root.

Add code with

logic.invoke('trigger')

to a component.

Start the project, open the console panel, and filter

log

messages.

The process felt tedious, costly, and the results were not intuitive, prompting the need for a right‑click online execution feature.

Benefits of Right‑Click Execution

Zero installation cost: Code runs in the browser without needing CLI tools.

Result visualization: Execution results are displayed visually instead of digging through the console.

Online mock input: Developers can mock inputs directly, greatly improving testing efficiency.

Test case saving: Input/output pairs can be saved as test cases to ensure code quality.

Exploration 1: Where Does Node Code Run?

Two options were considered: running code directly in the browser or starting a local service that bundles the code and sends it back to the browser. iMove chose the former to keep the barrier low, but a simple

eval

is insufficient.

Exploration 2: How to Run import/export

Each node is compiled into a separate

.js

file, so

import

statements are supported. Browsers natively support ES modules, so a

<script type="module">

tag is required.

<code># File structure
index.html
main.mjs</code>
<code><!--index.html-->
<script type="module">
  import sayHello from './main.js';
  say('Hello iMove!');
</script>
</code>
<code>// main.js
const say = (words) => console.log(words);
</code>

When importing a package like

lodash.get

, the browser treats it as a relative path, causing errors. Using an HTTP URL such as

import get from 'https://unpkg.com/lodash.get'

works, but the package is CommonJS (CJS) while the browser expects ES Module (ESM), leading to further failures.

2) SystemJS Attempt

SystemJS can load ES modules, but older versions that supported CJS are no longer maintained, and the approach introduces performance concerns.

3) New‑Generation JS Module CDN Hosting

CDNs like

unpkg

and

jspm

can serve ESM versions of packages. Experiments showed that loading

lodash.get

from

jspm

works while

unpkg

may not.

Exploration 3: Merging Multiple Files into a Single Executable

iMove’s output consists of multiple files, which would require an HTTP server for relative imports. Merging them into a single file eliminates this need. Example before merging:

<code>// a.js
import get from 'lodash.get';
const obj = {text: 'a', say: () => console.log(get(obj, 'text'))};
export default obj;

// b.js
import get from 'lodash.get';
const obj = {text: 'b', say: () => console.log(get(obj, 'text'))};
export default obj;

// main.js
import a from './a';
import b from './b';
a.say();
b.say();
</code>

After merging, dynamic imports and careful naming avoid global conflicts:

<code>// merged.js
const run = async () => {
  const modA = await (async () => {
    const get = (await import('https://jspm.dev/lodash.get')).default;
    const obj = {text: 'a', say: () => console.log(get(obj, 'text'))};
    return obj;
  })();
  const modB = await (async () => {
    const get = (await import('https://jspm.dev/lodash.get')).default;
    const obj = {text: 'b', say: () => console.log(get(obj, 'text'))};
    return obj;
  })();
  modA.say();
  modB.say();
};
run();
</code>

Note that the original

import

statements become dynamic imports inside function bodies.

Exploration 4: Communicating Between Scripts

To execute code strings without

eval

, a

&lt;script type="module"&gt;

element can be created dynamically:

<code>const script = document.createElement('script');
script.type = 'module';
script.text = 'code here';
document.body.appendChild(script);
</code>

After execution, results can be communicated back using custom events:

<code>// Listen for event
document.addEventListener('customEvent', function (evt) {
  console.log(evt.detail);
}, false);

// Dispatch event
document.dispatchEvent(new CustomEvent('customEvent', {detail: {text: 'iMove'}}));
</code>

Summary

The article walked through the challenges of adding online node‑code execution to iMove and resolved them mainly through the

http‑import

concept, leveraging Deno’s lightweight approach and modern CDN‑served JavaScript modules. This low‑cost, low‑risk solution improves developer experience and showcases a new direction for package management.

JavaScriptFrontend DevelopmentCDNESMiMove
Taobao Frontend Technology
Written by

Taobao Frontend Technology

The frontend landscape is constantly evolving, with rapid innovations across familiar languages. Like us, your understanding of the frontend is continually refreshed. Join us on Taobao, a vibrant, all‑encompassing platform, to uncover limitless potential.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.