diff --git a/src/pages/app/index.tsx b/src/pages/app/index.tsx index 85c98af..c6f355b 100644 --- a/src/pages/app/index.tsx +++ b/src/pages/app/index.tsx @@ -8,6 +8,7 @@ import errorBoundary from "../../utils/transpile/errorBoundary"; import "./style.css"; import { CSSTransition, TransitionGroup } from "react-transition-group"; import minifyCode from "../../utils/minify"; +// import { execToModule } from "../../utils/transpile/moduleImport"; // import ReactDOM from "react-dom/client"; export const App = () => { @@ -21,22 +22,17 @@ export const App = () => { const transforms: Transform[] = ["jsx", "typescript"]; const render = (element: ComponentType) => { - const Component = errorBoundary(element, errorCallBack); if (typeof element === "undefined") { errorCallBack(new SyntaxError("`render` must be called with valid JSX.")); } else { + const Component = errorBoundary(element, errorCallBack); setResults([Component]); } - // ReactDOM.createRoot(document.querySelector(".test-app") as HTMLElement).render( - // - // < Component /> - // - // ); }; // 开发环境下,useEffect会执行两次,模拟装载和卸载组件,生产环境没事。 useEffect(() => { - const allCpns = functionBlockList.map((item) => item.code).join("\n").replace(/export default/g, ""); + const allCpns = functionBlockList.map((item) => item.code).join("\n").replace(/export\s+default\s+([A-Za-z_$][A-Za-z0-9_$]*)/g, ""); const allPage = functionBlockList .map((item, index) => `<${item.cpnName} { ...props[${index}] }/>`) .join("\n"); @@ -60,7 +56,7 @@ export const App = () => { setTimeout(async () => { const minifiedCode = await minifyCode(allTransformed); - const codeToRun = minifiedCode.replace(/export default/g, "return") + const codeToRun = minifiedCode.replace(/export\s+default/g, "return") const ApplicationContext = evalCode( codeToRun, { @@ -68,8 +64,13 @@ export const App = () => { props: propsList, } ); - console.log(ApplicationContext); render(ApplicationContext); + // // console.log(ApplicationContext); + // const module = await execToModule(minifiedCode, { + // React: 'https://unpkg.com/react@17/umd/react.production.min.js', + // props: propsList, + // }) + // render(module.default); }, 1000); }, []); diff --git a/src/pages/editor/index.tsx b/src/pages/editor/index.tsx index 0b764b2..76821ae 100644 --- a/src/pages/editor/index.tsx +++ b/src/pages/editor/index.tsx @@ -132,7 +132,7 @@ export const Editor = () => { }, ]} > - + diff --git a/src/utils/minify/index.ts b/src/utils/minify/index.ts index 34d700d..0e4d57b 100644 --- a/src/utils/minify/index.ts +++ b/src/utils/minify/index.ts @@ -2,20 +2,23 @@ import { minify } from "terser"; import { jsxConst } from "../handler"; export default async function minifyCode(code: string) { + + console.log("minifyCode", code); + const replaced = code - .replace(RegExp(`React.createElement`, "g"), `rc`) - .replace(RegExp(`React.Fragment`, "g"), `rf`) - .replace(RegExp(`React.useState`, "g"), `rs`) - .replace(RegExp(`React.useEffect`, "g"), `re`) - .replace(RegExp(`React.Component`, "g"), `rcp`) - .replace(RegExp(`React.createContext`, "g"), `rcc`) - .replace(RegExp(`React.useContext`, "g"), `rcu`) - .replace(RegExp(`React.useReducer`, "g"), `rd`) - .replace(RegExp(`React.memo`, "g"), `rm`) - .replace( - jsxConst, - `${jsxConst} const rc=React.createElement,rf=React.Fragment,rs=React.useState,re=React.useEffect,rcp=React.Component,rcc=React.createContext,rcu=React.useContext,rd=React.useReducer,rm=React.memo;` - ); + // .replace(RegExp(`React.createElement`, "g"), `rc`) + // .replace(RegExp(`React.Fragment`, "g"), `rf`) + // .replace(RegExp(`React.useState`, "g"), `rs`) + // .replace(RegExp(`React.useEffect`, "g"), `re`) + // .replace(RegExp(`React.Component`, "g"), `rcp`) + // .replace(RegExp(`React.createContext`, "g"), `rcc`) + // .replace(RegExp(`React.useContext`, "g"), `rcu`) + // .replace(RegExp(`React.useReducer`, "g"), `rd`) + // .replace(RegExp(`React.memo`, "g"), `rm`) + // .replace( + // jsxConst, + // `${jsxConst} const rc=React.createElement,rf=React.Fragment,rs=React.useState,re=React.useEffect,rcp=React.Component,rcc=React.createContext,rcu=React.useContext,rd=React.useReducer,rm=React.memo;` + // ); const { code: minifiedCode } = await minify(replaced, { compress: { diff --git a/src/utils/transpile/index.ts b/src/utils/transpile/index.ts index e9b741d..bebf789 100644 --- a/src/utils/transpile/index.ts +++ b/src/utils/transpile/index.ts @@ -27,6 +27,7 @@ export const generateElement = ( const firstPassTransforms: Transform[] = ["jsx"]; enableTypeScript && firstPassTransforms.push("typescript"); + // 通过compose函数,将多个函数组合成一个函数,用于Inline编辑器的代码转换 const transformed = compose( addJsxConst, transform({ transforms: ["imports"] }), @@ -74,5 +75,11 @@ export const renderElementAsync = ( const Cpn = evalCode(codeTorun, { React, ...scope, render }); + // if (!React.isValidElement(Cpn)) { + // return errorCallback( + // new SyntaxError("The Code didn't return a valid JSX element!") + // ); + // } + render(Cpn); }; diff --git a/src/utils/transpile/moduleImport.ts b/src/utils/transpile/moduleImport.ts new file mode 100644 index 0000000..1307da0 --- /dev/null +++ b/src/utils/transpile/moduleImport.ts @@ -0,0 +1,37 @@ +import { Transform } from "sucrase"; +import transform from "./transform"; +import minifyCode from "../minify"; + +const transforms: Transform[] = ["jsx", "typescript"]; + +export const execToModule = async ( + code: string, + scope: { [key: string]: any } = {} +): Promise => { + // 将scope对象中的属性转换为import语句 + const importStatements = Object.keys(scope) + .map(([key, path]) => `import ${key} from '${path}';`) + .join("\n"); + + // 添加到code之前 + const scopedCode = `${importStatements}\n${code}`; + + // 使用Babel或其他工具进行转换 + const allTransformed = transform({ transforms })(scopedCode); + const minifiedCode = await minifyCode(allTransformed); + + // 创建并导入模块 + return new Promise((resolve) => { + (async () => { + // 创建一个Blob对象 + const blob = new Blob([minifiedCode], { type: "application/javascript" }); + // 创建一个URL对象 + const url = URL.createObjectURL(blob); + // 动态导入模块 + const module = await import(url); + resolve(module); + // 释放URL对象 + URL.revokeObjectURL(url); + })(); + }); +}; diff --git a/src/utils/transpile/transform.ts b/src/utils/transpile/transform.ts index f00b04a..9d51a86 100644 --- a/src/utils/transpile/transform.ts +++ b/src/utils/transpile/transform.ts @@ -11,5 +11,6 @@ export default function transform(opts: Options = {}) { ? opts.transforms.filter(Boolean) : defaultTransforms; - return (code: string) => _transform(code, { transforms }).code; + return (code: string) => + _transform(code, { transforms, production: true }).code; }