diff --git a/src/components/Playground/Output/Preview/Render.tsx b/src/components/Playground/Output/Preview/Render.tsx
new file mode 100644
index 0000000..940a80f
--- /dev/null
+++ b/src/components/Playground/Output/Preview/Render.tsx
@@ -0,0 +1,77 @@
+import iframeRaw from '@/components/Playground/Output/Preview/iframe.html?raw'
+
+interface RenderProps {
+ iframeKey: string
+ compiledCode: string
+ onError?: (errorMsg: string) => void
+}
+
+interface IMessage {
+ type: 'LOADED' | 'ERROR' | 'UPDATE' | 'DONE'
+ msg: string
+ data: {
+ compiledCode: string
+ }
+}
+
+const getIframeUrl = (iframeRaw: string) => {
+ const shimsUrl = '//unpkg.com/es-module-shims/dist/es-module-shims.js'
+ // 判断浏览器是否支持esm ,不支持esm就引入es-module-shims
+ const newIframeRaw =
+ typeof import.meta === 'undefined'
+ ? iframeRaw.replace(
+ '',
+ ``
+ )
+ : iframeRaw
+ return URL.createObjectURL(new Blob([newIframeRaw], { type: 'text/html' }))
+}
+
+const iframeUrl = getIframeUrl(iframeRaw)
+
+const Render = ({ iframeKey, compiledCode, onError }: RenderProps) => {
+ const iframeRef = useRef(null)
+ const [loaded, setLoaded] = useState(false)
+
+ const handleMessage = ({ data }: { data: IMessage }) => {
+ const { type, msg } = data
+ switch (type) {
+ case 'LOADED':
+ setLoaded(true)
+ break
+ case 'ERROR':
+ onError?.(msg)
+ break
+ case 'DONE':
+ onError?.('')
+ }
+ }
+
+ useEffect(() => {
+ window.addEventListener('message', handleMessage)
+
+ return () => {
+ window.removeEventListener('message', handleMessage)
+ }
+ }, [])
+
+ useEffect(() => {
+ if (loaded) {
+ iframeRef.current?.contentWindow?.postMessage({
+ type: 'UPDATE',
+ data: { compiledCode }
+ } as IMessage)
+ }
+ }, [compiledCode, loaded])
+
+ return (
+
+ )
+}
+
+export default Render
diff --git a/src/components/Playground/Output/Preview/index.tsx b/src/components/Playground/Output/Preview/index.tsx
index 8620120..2f6dd0b 100644
--- a/src/components/Playground/Output/Preview/index.tsx
+++ b/src/components/Playground/Output/Preview/index.tsx
@@ -1,8 +1,8 @@
import '@/components/Playground/Output/Preview/preview.scss'
import { IFiles, IImportMap } from '@/components/Playground/shared'
import Compiler from '@/components/Playground/compiler'
-import iframeRaw from '@/components/Playground/Output/Preview/iframe.html?raw'
-import { ENTRY_FILE_NAME } from '@/components/Playground/files.ts'
+import { ENTRY_FILE_NAME } from '@/components/Playground/files'
+import Render from '@/components/Playground/Output/Preview/Render'
interface PreviewProps {
iframeKey: string
@@ -10,79 +10,27 @@ interface PreviewProps {
importMap: IImportMap
}
-interface IMessage {
- type: 'LOADED' | 'ERROR' | 'UPDATE' | 'DONE'
- msg: string
- data: {
- compiledCode: string
- }
-}
-
-const getIframeUrl = (iframeRaw: string) => {
- const shimsUrl = '//unpkg.com/es-module-shims@1.8.0/dist/es-module-shims.js'
- // 判断浏览器是否支持esm ,不支持esm就引入es-module-shims
- const newIframeRaw =
- typeof import.meta === 'undefined'
- ? iframeRaw.replace(
- '',
- ``
- )
- : iframeRaw
- return URL.createObjectURL(new Blob([newIframeRaw], { type: 'text/html' }))
-}
-
-const iframeUrl = getIframeUrl(iframeRaw)
-
const Preview = ({ iframeKey, files, importMap }: PreviewProps) => {
- const iframeRef = useRef(null)
const [errorMsg, setErrorMsg] = useState('')
- const [loaded, setLoaded] = useState(false)
+ const [compiledCode, setCompiledCode] = useState('')
- const handleMessage = ({ data }: { data: IMessage }) => {
- const { type, msg } = data
- switch (type) {
- case 'LOADED':
- setLoaded(true)
- break
- case 'ERROR':
- setErrorMsg(msg)
- break
- case 'DONE':
- setErrorMsg('')
- }
+ const handleOnError = (errorMsg: string) => {
+ setErrorMsg(errorMsg)
}
- useEffect(() => {
- window.addEventListener('message', handleMessage)
-
- return () => {
- window.removeEventListener('message', handleMessage)
- }
- }, [])
-
useEffect(() => {
Compiler.compile(files, importMap, [ENTRY_FILE_NAME])
.then((result) => {
- if (loaded) {
- iframeRef.current?.contentWindow?.postMessage({
- type: 'UPDATE',
- data: { compiledCode: result.outputFiles[0].text }
- } as IMessage)
- }
+ setCompiledCode(result.outputFiles[0].text)
})
.catch((e: Error) => {
setErrorMsg(`编译失败:${e.message}`)
})
- }, [files, Compiler, loaded])
+ }, [files, Compiler])
return (
-
+
{errorMsg &&
{errorMsg}
}
)
diff --git a/src/components/Playground/compiler.ts b/src/components/Playground/compiler.ts
index 566eac9..d7a9bea 100644
--- a/src/components/Playground/compiler.ts
+++ b/src/components/Playground/compiler.ts
@@ -14,7 +14,10 @@ class Compiler {
constructor() {
try {
void esbuild
- .initialize({ worker: true, wasmURL: 'https://esm.sh/esbuild-wasm/esbuild.wasm' })
+ .initialize({
+ worker: true,
+ wasmURL: 'https://esm.sh/esbuild-wasm@0.19.12/esbuild.wasm'
+ })
.finally(() => {
this.init = true
})