1.编译
编译用的 @babel/standalone,这个是 babel 的浏览器版本。
可以用它实时把 tsx 代码编译为 js。
///拿到内容用babel.transform编译,指定 typescript 和 react 的 preset
const res = transform(textareaRef.current.value, { presets: ['react', 'typescript'], filename: 'guang.tsx' });
问题1: import 模块找不到
解决方法: import 的 url 可以用 blob url 可以把JS代码 用URL.createObjectURL和new Blob的方式变为一个 url
<script>
const code1 =` function add(a, b) { return a + b; } export { add }; `;
const url = URL.createObjectURL(new Blob([code1], { type: 'application/javascript' }));
const code2 = `import { add } from "${url}"; console.log(add(2, 3));`;
const script = document.createElement('script'); script.type="module"; s
cript.textContent = code2; document.body.appendChild(script);
</script>
babel插件
- babel 编译流程分为parse transform genrate
- babel 插件就是在 transform 的阶段增删改 AST 的
编辑器部分
@monaco-editor/react
预览部分
iframe,然后加一个通信机制,左边编辑器的结果,编译之后传到 iframe 里渲染就好了
import React from 'react'
//?raw 是通过字符串引入
import iframeRaw from './iframe.html?raw';
const iframeUrl = URL.createObjectURL(new Blob([iframeRaw], { type: 'text/html' }));
const Preview: React.FC = () => { return ( <iframe src={iframeUrl} style={{ width: '100%', height: '100%', padding: 0, border: 'none' }} /> ) }
export default Preview;
总结
- 编辑器部分 @monaco-editor/react
- @babel/standalone 在浏览器里编译
- 编译过程中用自己写的 babel 插件实现 import 的 source 的修改,变为 URL.createObjectURL + Blob 生成的 blob url,把模块内容内联进去。
- 对于 react、react-dom 这种包,用 import maps 配合 esm.sh 网站来引入。
- iframe 预览生成的内容,url 同样是把内容内联到 src 里,生成 blob url