浏览器动态生成/执行 JS/TS 代码:完整技术方案
浏览器动态生成/执行 JS/TS 代码:完整技术方案
在浏览器中动态生成 JS/TS 代码并即时渲染、执行,是前端常用能力(如在线编辑器、低代码平台、动态脚本注入)。我把所有主流、可用、安全的技术方案按使用场景、优缺点、适用范围整理好,你可以直接按需选择。
一、核心基础方案(纯原生 JS,无依赖)
适用于简单场景,无需第三方库,浏览器原生支持。
1. eval() 函数
最直接的执行字符串代码的方式,执行作用域为当前作用域。
// 动态生成代码
const code = "const a = 10; console.log(a + 20); document.body.innerHTML = '动态渲染:' + (a+20)";
// 即时执行
eval(code);
✅ 优点:最简单、零依赖、作用域灵活
❌ 缺点:安全风险极高(XSS 攻击)、调试困难、性能一般
⚠️ 适用:绝对可信的代码(自己生成的内部代码),绝不用于用户输入代码
2. new Function()
基于字符串创建函数并执行,作用域独立(比 eval 更安全一点)。
const code = "return x + y";
const fn = new Function("x", "y", code);
console.log(fn(1,2)); // 3
// 执行完整代码
const fullCode = "document.body.style.background = 'lightblue'";
new Function(fullCode)();
✅ 优点:独立作用域、无变量污染、比 eval 安全
❌ 缺点:仍有安全风险、无法调试 TS
⚠️ 适用:简单动态逻辑、纯 JS 代码
3. 动态创建 <script> 标签
最常用、最标准的动态脚本注入方式,浏览器原生解析执行。
// 1. 生成代码字符串
const jsCode = `
console.log('动态脚本执行');
document.querySelector('#app').innerHTML = '<h1>动态渲染成功</h1>';
`;
// 2. 创建 script 标签并注入
const script = document.createElement('script');
script.textContent = jsCode;
document.body.appendChild(script);
✅ 优点:原生标准、支持完整 JS 语法、可异步加载、调试友好
❌ 缺点:不支持 TS、会污染全局作用域
⚠️ 适用:绝大多数动态 JS 执行场景
4. Blob + URL.createObjectURL + 动态 Script
企业级标准方案:将代码转为二进制文件,生成临时 URL 执行,支持调试、作用域独立、无全局污染。
// 动态代码
const code = "console.log('Blob 执行'); document.body.innerHTML = 'Blob 动态渲染'";
// 1. 生成 Blob 对象
const blob = new Blob([code], { type: 'application/javascript' });
// 2. 生成临时 URL
const url = URL.createObjectURL(blob);
// 3. 动态加载执行
const script = document.createElement('script');
script.src = url;
document.body.appendChild(script);
// 4. 释放资源
URL.revokeObjectURL(url);
✅ 优点:安全、可调试(浏览器显示为独立文件)、无全局污染
❌ 缺点:代码稍多、不支持 TS
⚠️ 适用:生产环境、在线编辑器、低代码平台(首选原生方案)
二、TypeScript 专属方案(动态生成 TS → 即时编译 → 运行)
TS 不能直接在浏览器运行,必须先编译为 JS,以下是浏览器端实时编译 TS 的成熟方案:
1. TypeScript Compiler API(官方编译器)
浏览器直接引入 TS 官方库,实时编译 TS → JS → 执行。
<!-- 引入官方 TS 编译器 -->
<script src="https://cdn.jsdelivr.net/npm/typescript@5.0.0/lib/typescript.umd.js"></script>
<script>
// 1. 动态生成 TS 代码
const tsCode = `
const name: string = "动态TS";
const num: number = 100;
document.body.innerHTML = "<h2>" + name + ":" + num + "</h2>";
`;
// 2. 浏览器端实时编译 TS → JS
const jsCode = ts.transpile(tsCode, {
target: ts.ScriptTarget.ESNext,
module: ts.ModuleKind.ESModule
});
// 3. 执行编译后的 JS
const blob = new Blob([jsCode], { type: 'application/javascript' });
const url = URL.createObjectURL(blob);
document.body.appendChild(Object.assign(document.createElement('script'), { src: url }));
</script>
✅ 优点:官方标准、支持完整 TS 语法、稳定可靠
❌ 缺点:库体积较大(~1.5MB)、首次加载慢
⚠️ 适用:需要完整 TS 支持的专业场景(在线 IDE、低代码)
2. esbuild-wasm(极速编译器)
目前最快的浏览器端 TS/JS 编译器,体积小、编译速度秒杀官方 TS。
// 异步加载 esbuild 编译器
import * as esbuild from 'https://cdn.jsdelivr.net/npm/esbuild-wasm@0.20.0/esm/browser.min.js';
await esbuild.initialize({
wasmURL: 'https://cdn.jsdelivr.net/npm/esbuild-wasm@0.20.0/esm/esbuild.wasm'
});
// 动态 TS 代码
const tsCode = "const a:number = 1; console.log(a)";
// 极速编译
const result = await esbuild.transform(tsCode, {
loader: 'ts',
target: 'es2020'
});
// 执行 JS
eval(result.code);
✅ 优点:极快、体积小、支持 TS/JSX/ES6+
❌ 缺点:需要 WASM 支持(现代浏览器都支持)
⚠️ 适用:追求性能的场景(最佳 TS 动态编译方案)
三、高级沙箱方案(安全隔离,禁止访问全局)
如果执行不可信代码(用户输入代码),必须用沙箱隔离,防止访问 window、document 等全局对象。
1. iframe 沙箱(最安全、原生支持)
把代码放在独立 iframe 中运行,完全隔离主页面,企业级安全方案。
const iframe = document.createElement('iframe');
iframe.sandbox = 'allow-scripts'; // 仅允许执行脚本,禁止访问父页面
iframe.style.display = 'none';
document.body.appendChild(iframe);
// 动态代码注入 iframe
const code = "document.body.innerHTML = '沙箱内渲染'";
iframe.contentDocument.write("<script>"+code+"</script>");
✅ 优点:绝对安全、完全隔离、无 XSS 风险
❌ 缺点:通信麻烦(需 postMessage)
⚠️ 适用:执行用户代码、在线代码编辑器、低代码平台
2. Secure ECMAScript (SES)
轻量级 JS 沙箱,冻结全局对象,禁止代码访问危险 API。
// 引入 SES
import 'https://cdn.jsdelivr.net/npm/ses@1.0.0/dist/umd/ses.min.js';
// 创建沙箱
const sandbox = SES.makeSESRootRealm();
// 执行隔离代码
sandbox.evaluate("console.log('沙箱运行')", { console });
✅ 优点:轻量、无 iframe、安全可控
❌ 缺点:不支持 DOM 操作
⚠️ 适用:纯逻辑代码隔离
四、成熟开源库(开箱即用,无需手写编译)
直接用成熟库,快速实现动态代码生成+执行+渲染:
- CodeMirror / Monaco Editor(VS Code 内核)
- 支持 TS/JS 实时语法提示、编译、运行、渲染
- Vue/React 动态渲染
- 动态生成组件代码 → 编译 → 挂载到页面
- Vite Runtime
- 浏览器端实时编译 TS/JSX,急速热更新
五、方案选型速查表
| 需求场景 | 推荐方案 | 安全等级 | 支持 TS |
|---|---|---|---|
| 简单内部 JS 执行 | 动态 <script> / Blob |
中 | ❌ |
| 生产环境 JS 执行 | Blob + 动态 Script | 高 | ❌ |
| 动态 TS 编译执行 | esbuild-wasm | 中 | ✅ |
| 专业 TS 支持 | TypeScript 官方 API | 中 | ✅ |
| 执行用户不可信代码 | iframe 沙箱 | 极高 | ✅(编译后) |
| 在线编辑器/低代码 | Monaco Editor + iframe | 极高 | ✅ |
六、关键注意事项
- 安全第一
- 绝对不要用
eval/new Function执行用户输入代码 - 执行外部代码必须用沙箱
- 绝对不要用
- TS 必须编译
- 浏览器不识别 TS,必须用 esbuild/TS 编译器转 JS
- 调试优化
- 优先用 Blob 方案,浏览器会把动态代码识别为独立文件,支持断点调试
- 性能
- 频繁执行用 esbuild,简单场景用原生 Script
总结
- 纯 JS 动态执行:首选
Blob + 动态Script(安全、可调试) - TS 动态执行:首选
esbuild-wasm(极速、轻量) - 安全执行用户代码:必须用
iframe 沙箱 - 专业场景:直接用
Monaco Editor(VS Code 内核)
这是目前浏览器端所有成熟、可用、生产级的动态代码生成与执行方案,覆盖了从简单到复杂、从安全到高性能的全部需求。
- 本文标签: JavaScript TypeScript 前端
- 本文链接: http://t-leader.cn/article/838
- 版权声明: 本文由站长原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权