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.
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 -din the project root.
Add code with
logic.invoke('trigger')to a component.
Start the project, open the console panel, and filter
logmessages.
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
evalis insufficient.
Exploration 2: How to Run import/export
Each node is compiled into a separate
.jsfile, so
importstatements 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
unpkgand
jspmcan serve ESM versions of packages. Experiments showed that loading
lodash.getfrom
jspmworks while
unpkgmay 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
importstatements become dynamic imports inside function bodies.
Exploration 4: Communicating Between Scripts
To execute code strings without
eval, a
<script type="module">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‑importconcept, 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.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.