diff --git a/public/sandbox.html b/public/sandbox.html index 44a9821..197df00 100644 --- a/public/sandbox.html +++ b/public/sandbox.html @@ -1,37 +1,43 @@ - - - - - - -
- + const handleError = (err) => { + console.error(err, "CAUGHT"); + parent.postMessage({ error: err.toString() }, "*"); + }; - - + window.addEventListener("error", (ev) => { + console.log(ev); + handleError(ev.error); + }); + + window.onerror = (e) => { + console.log(e) + } + + const run = (code) => { + console.log("Ran") + if (!code) return + + (async () => { + await import(createUri(code)) + })().catch((e) => { + console.log(e) + handleError(e) + }); + } + + window.addEventListener( + "message", + (e) => { + run(e.data.code) + }, + false + ); + + \ No newline at end of file diff --git a/src/bundler/index.ts b/src/bundler/index.ts index d356a26..22a9f7b 100644 --- a/src/bundler/index.ts +++ b/src/bundler/index.ts @@ -31,6 +31,8 @@ class Bundler { config: BuildOptions = { bundle: true, write: false, + platform: "browser", + format: "esm", define: { "process.env.NODE_ENV": `"production"`, global: "window", diff --git a/src/bundler/plugins/loader.plugin.ts b/src/bundler/plugins/loader.plugin.ts index ac8956b..9edb9b3 100644 --- a/src/bundler/plugins/loader.plugin.ts +++ b/src/bundler/plugins/loader.plugin.ts @@ -1,36 +1,48 @@ import { Loader, OnLoadResult } from "esbuild-wasm"; import { unix as path } from "path-fx"; import { BuildInput } from ".."; +import { BundlingError } from "../errors"; import { createPlugin, getLoaderFromPath } from "./helpers"; const plugin = createPlugin((options) => ({ name: "loader-plugin", setup(build) { - build.onLoad({ filter: new RegExp(path.join(options.entry)) }, (args) => { - return { - loader: getLoaderFromPath(args.path, options.loader), - contents: options.tree[path.join(options.entry)], - }; - }); + build.onLoad( + { filter: new RegExp(path.join(options.entry)), namespace: "entry" }, + (args) => { + const contents = options.tree[path.join(options.entry)]; + + if (!contents) { + return null; + } + + return { + loader: getLoaderFromPath(args.path, options.loader), + contents, + }; + } + ); /** * Resolve relative modules imports */ - build.onLoad({ filter: /^\.+\// }, (args) => { + build.onLoad({ filter: /^\.+\//, namespace: "relative" }, (args) => { const contents = options.tree[path.join("/", args.path)]; + if (!contents) return null; + return { loader: getLoaderFromPath(args.path, options.loader), contents, }; }); - build.onLoad({ filter: /.*/ }, async (args) => { - let contents = options.tree[args.path]; + build.onLoad({ filter: /.*/, namespace: "main" }, async (args) => { + const contents = options.tree[args.path] || options.tree["/" + args.path]; if (!contents) { - contents = options.tree["/" + args.path]; + return null; } const result: OnLoadResult = { @@ -41,32 +53,6 @@ const plugin = createPlugin((options) => ({ return result; }); - - // build.onLoad({ filter: /.css$/ }, async (args: any) => { - // const { data, request } = await axios.get(args.path); - - // const contents = normalizeCss(data); - - // const result: OnLoadResult = { - // loader: "jsx", - // contents, - // resolveDir: new URL("./", request.responseURL).pathname, - // }; - - // await fileCache.setItem(args.path, result); - - // return result; - // }); - - // build.onLoad({ filter: /.*/ }, async (args) => { - // const result: OnLoadResult = { - // loader: "jsx", - // contents: "", - // resolveDir: new URL("./", args.path).pathname, - // }; - - // return result; - // }); }, })); diff --git a/src/bundler/plugins/resolver.plugin.ts b/src/bundler/plugins/resolver.plugin.ts index 010706c..3a3ef2d 100644 --- a/src/bundler/plugins/resolver.plugin.ts +++ b/src/bundler/plugins/resolver.plugin.ts @@ -1,4 +1,4 @@ -import { unix as path } from "path-fx"; +import { unix } from "path-fx"; import { BuildInput } from ".."; import { createPlugin } from "./helpers"; @@ -11,9 +11,9 @@ const plugin = createPlugin((options) => ({ * Resolve the entry file eg. `index.js` */ build.onResolve( - { filter: new RegExp(path.join("/", options.entry)) }, - (args: any) => { - return { path: args.path, namespace: "a" }; + { filter: new RegExp(unix.join("/", options.entry)) }, + (args) => { + return { path: args.path, namespace: "entry" }; } ); @@ -22,7 +22,7 @@ const plugin = createPlugin((options) => ({ */ build.onResolve({ filter: /^\.+\// }, (args) => { return { - namespace: "a", + namespace: "relative", path: args.path, }; }); @@ -30,10 +30,22 @@ const plugin = createPlugin((options) => ({ /** * Resolve main module files */ - build.onResolve({ filter: /.*/ }, async (args: any) => { + build.onResolve({ filter: /.*/ }, async (args) => { + let path = unix.join("/", args.path); + + if (path in options.tree) { + return { + namespace: "main", + path, + }; + } + + path = new URL(args.path, "https://cdn.skypack.dev").href; + return { - namespace: "a", - path: args.path, + namespace: "skypack", + path: path, + external: true, }; }); }, diff --git a/src/components/preview/Preview.tsx b/src/components/preview/Preview.tsx index 3c4217e..5493e5b 100644 --- a/src/components/preview/Preview.tsx +++ b/src/components/preview/Preview.tsx @@ -17,26 +17,29 @@ const Preview: React.FC = () => { const result = useMemo(() => createSnippet({ html, css }), [html, css]); + const postCode = (target: HTMLIFrameElement) => { + target.contentWindow.postMessage({ code: js }, "*"); + }; + useEffect(() => { if (!iframe.current) return; iframe.current.srcdoc = result; }, [result]); useEffect(() => { - if (!iframe.current) return; - - iframe.current.contentWindow.postMessage({ code: js }, "*"); + postCode(iframe.current); + }, [js, result]); + useEffect(() => { const handler = (ev: MessageEvent<{ error: Error }>) => { if (typeof ev.data?.error !== "string") return; - dispatch(UPDATE_ERROR(ev.data.error)); }; window.addEventListener("message", (ev) => handler(ev)); return () => window.removeEventListener("message", (ev) => handler(ev)); - }, [js, result]); + }, []); return (
@@ -46,6 +49,7 @@ const Preview: React.FC = () => {