Skip to content

Commit

Permalink
fix: improve preview code execution
Browse files Browse the repository at this point in the history
  • Loading branch information
sidwebworks committed Jun 10, 2022
1 parent 98a7779 commit 94f1cc9
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 106 deletions.
74 changes: 40 additions & 34 deletions public/sandbox.html
Original file line number Diff line number Diff line change
@@ -1,37 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<script type="module">
const handleError = (err) => {
console.error(JSON.stringify(err))
}
<script type="module">

window.addEventListener("error", (ev) => {
ev.preventDefault()
handleError(ev.error)
})
function createUri(raw) {
const blob = new Blob([String.raw({raw})], {type: 'text/javascript'})
const uri = URL.createObjectURL(blob);
return uri;
}

window.addEventListener("message", (ev) => {
if (!ev.data?.code) return
try {
eval(e.data.code)
} catch (error) {
handleError(error)
}
})
</script>
</head>
<body>
<div id="root"></div>
<script>
window.addEventListener(
"message",
(event) => {
console.log(event);
},
false
);
</script>
const handleError = (err) => {
console.error(err, "CAUGHT");
parent.postMessage({ error: err.toString() }, "*");
};

</body>
</html>
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
);

</script>
2 changes: 2 additions & 0 deletions src/bundler/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class Bundler {
config: BuildOptions = {
bundle: true,
write: false,
platform: "browser",
format: "esm",
define: {
"process.env.NODE_ENV": `"production"`,
global: "window",
Expand Down
58 changes: 22 additions & 36 deletions src/bundler/plugins/loader.plugin.ts
Original file line number Diff line number Diff line change
@@ -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<BuildInput>((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 = {
Expand All @@ -41,32 +53,6 @@ const plugin = createPlugin<BuildInput>((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;
// });
},
}));

Expand Down
28 changes: 20 additions & 8 deletions src/bundler/plugins/resolver.plugin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { unix as path } from "path-fx";
import { unix } from "path-fx";
import { BuildInput } from "..";
import { createPlugin } from "./helpers";

Expand All @@ -11,9 +11,9 @@ const plugin = createPlugin<BuildInput>((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" };
}
);

Expand All @@ -22,18 +22,30 @@ const plugin = createPlugin<BuildInput>((options) => ({
*/
build.onResolve({ filter: /^\.+\// }, (args) => {
return {
namespace: "a",
namespace: "relative",
path: args.path,
};
});

/**
* 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,
};
});
},
Expand Down
14 changes: 9 additions & 5 deletions src/components/preview/Preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<div className={"preview-wrapper relative h-full"}>
Expand All @@ -46,6 +49,7 @@ const Preview: React.FC = () => {

<iframe
ref={iframe}
onLoad={(e) => postCode(e.target as HTMLIFrameElement)}
title="preview"
srcDoc={result}
className="h-full"
Expand Down
58 changes: 35 additions & 23 deletions src/components/preview/preview.helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,42 @@ import { template } from "lodash-es";

const templates = {
js: template(`
<script type="module">
const handleError = (err) => {
console.error(err)
parent.postMessage({ error: err.toString() }, "*")
}
window.addEventListener("error", (ev) => {
ev.preventDefault()
handleError(ev.error)
})
window.addEventListener("message", (ev) => {
if (!ev.data?.code) return
try {
eval(ev.data.code)
parent.postMessage({ error: "" }, "*")
} catch (error) {
handleError(error)
<script type="module" async>
function createUri(raw) {
const blob = new Blob([String.raw({raw})], {type: 'text/javascript'})
const uri = URL.createObjectURL(blob);
return uri;
}
}, false)
</script>`),
const handleError = (err) => {
console.error(err);
parent.postMessage({ error: err.toString() }, "*");
};
window.addEventListener("error", (ev) => {
ev.preventDefault()
handleError(ev.error);
});
const run = (code) => {
if (!code) return
(async () => {
document.body.innerHTML = document.body.innerHTML
const uri = createUri(code)
await import(uri)
})().then(() => {
parent.postMessage({ error: '' }, "*");
}).catch(handleError)
}
window.addEventListener(
"message",
(e) => run(e.data.code),
false
);
</script>
`),
css: template(`<style> <%- code %> </style>`),
};

Expand All @@ -47,6 +62,3 @@ export const createSnippet = ({

return output;
};



1 comment on commit 94f1cc9

@vercel
Copy link

@vercel vercel bot commented on 94f1cc9 Jun 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

web-pen – ./

web-pen-sidwebworks.vercel.app
web-pen.vercel.app
web-pen-git-master-sidwebworks.vercel.app

Please sign in to comment.