You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在浏览器中从字符串运行含外部库的JavaScript?(SvelteKit)

解决方案

1. 预导入库并注入动态函数作用域

在executeFunction所在模块预先导入需要的外部库,通过new Function的参数将库注入动态代码的作用域,无需修改调用方参数,避免大规模重构。

示例代码:

import imageConversion from 'image-conversion';
import type { LoadOutput } from './your-types'; // 替换为实际类型路径

export async function executeFunction(data: LoadOutput, input: Record<string, any>): Promise<any> {
    let args = [];
    for (let param of data.functionTree[0].parameters) {
        let value = input[param.name];
        if(!value) {
            return undefined;
        }
        args.push(value);
    }

    // 将预导入的库作为参数传入,让动态代码可直接使用
    let func = new Function('imageConversion', `return ${data.jsCode}`)(imageConversion);
    return await func.call(null, ...args);
}

动态代码中即可直接调用库方法:

function(img) {
    return imageConversion.compress(img, { quality: 0.5 });
}

若需多个库,扩展参数列表即可:

import imageConversion from 'image-conversion';
import anotherLib from 'another-lib';

// ...

let func = new Function('imageConversion', 'anotherLib', `return ${data.jsCode}`)(imageConversion, anotherLib);

2. 全局挂载库(临时场景适用)

在SvelteKit客户端初始化逻辑中,将预导入的库挂载到window对象,动态代码可直接访问全局变量。

示例:

// 在+layout.svelte或初始化脚本中
import imageConversion from 'image-conversion';

if (typeof window !== 'undefined') {
    (window as any).imageConversion = imageConversion;
}

executeFunction无需修改:

export async function executeFunction(data: LoadOutput, input: Record<string, any>): Promise<any> {
    // ... 原有逻辑 ...
    let func = new Function('return ' + data.jsCode)();
    return await func.call(null, ...args);
}

注意:该方式会污染全局作用域,仅适合临时验证场景,不推荐大型项目使用。

3. 动态加载库并传入作用域(按需加载场景)

若无需预先导入所有库,可在executeFunction内动态加载所需库,再传入动态代码作用域,减少初始打包体积。

示例:

export async function executeFunction(data: LoadOutput, input: Record<string, any>): Promise<any> {
    // ... 原有逻辑 ...

    // 假设data中包含需要加载的库列表,如data.requiredLibs = ['image-conversion']
    const libs = await Promise.all(
        (data.requiredLibs || []).map(lib => import(lib))
    );
    // 提取库的导出内容(根据库的导出方式调整)
    const libValues = libs.map(lib => lib.default || lib);
    // 生成库对应的变量名(可根据需求调整命名规则)
    const paramNames = (data.requiredLibs || []).map(lib => lib.split('/').pop() || lib);
    // 创建函数并传入库
    let func = new Function(...paramNames, `return ${data.jsCode}`)(...libValues);
    return await func.call(null, ...args);
}

注意:需确保库已通过npm安装,且Vite能正确解析裸模块名;动态代码需使用约定的变量名调用库。

为什么直接在动态代码中加import会报错?

new Function创建的代码运行在非模块作用域中,浏览器无法解析裸模块名(如image-conversion)——浏览器无法识别该模块的实际URL路径。即使在模块中使用new Function,其代码也不会自动继承模块的导入能力,必须显式注入依赖。


内容的提问来源于stack exchange,提问作者Finn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 10:12:51