Skip to content

Instantly share code, notes, and snippets.

@mizchi
Created February 19, 2021 09:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mizchi/221b519b1aec01950f41b8bfec08ec1c to your computer and use it in GitHub Desktop.
Save mizchi/221b519b1aec01950f41b8bfec08ec1c to your computer and use it in GitHub Desktop.
import { GENERATED_CSS_PREFIX } from "./constants";
import * as uniroll from "uniroll";
import ts from "typescript";
import { svelte } from "./index";
import fetch from "isomorphic-unfetch";
import vm from "vm";
import fs from "fs";
global.fetch = fetch;
const App = `
<script lang="ts">
export let foo: string;
import { onMount } from 'svelte';
let n = 0;
const onClick = () => {
n = n + 1
}
let mounted = false;
onMount(() => {
mounted = true;
});
</script>
{#if mounted}hydrated{/if}
<button on:click={onClick}>{foo}{n}</button>
<style>
button {
color: red;
}
</style>
`;
const resolveIdFallback = (id: string) => {
if (id.startsWith(GENERATED_CSS_PREFIX)) {
return;
}
if (id.startsWith("https://")) {
return id;
}
if (id === "svelte") {
return "https://cdn.skypack.dev/svelte";
}
if (id === "svelte/internal") {
return "https://cdn.skypack.dev/svelte/internal";
}
if (id.startsWith(".")) return;
};
async function main() {
const bundled = await uniroll.bundle({
input: "/index.ts",
resolveIdFallback,
extraPlugins: [
svelte({
emitCss: true,
target: ts.ScriptTarget.ES5,
resolveIdFallback,
svelteOptions: {
hydratable: true,
generate: "ssr",
css: false,
},
}),
{
name: "transform-cdn",
transform(code: string, id: string) {
if (id.startsWith("https://")) {
const out = ts.transpileModule(code, {
compilerOptions: {
module: ts.ModuleKind.ESNext,
target: ts.ScriptTarget.ES5,
},
});
return {
code: out.outputText,
map: out.sourceMapText,
};
}
},
} as any,
],
files: {
"/App.svelte": App,
"/index.ts": `
import App from './App.svelte';
// out.constructor.prototype.x = 1;
// Object.prototaype.x = 1;
out = App.render({foo: 'hello'});
`,
},
});
const out = await bundled.generate({ format: "es" });
const code = out.output[0].code;
const sandbox: any = { out: Object.create(null) };
vm.runInNewContext(code, sandbox);
const html: string = sandbox.out.html;
let css = ``;
for (const output of out.output) {
if (
output.type === "asset" &&
output.fileName.startsWith("uniroll-svelte")
) {
css += output.source;
}
}
const bundled2 = await uniroll.bundle({
input: "/index.ts",
extraPlugins: [
svelte({
emitCss: true,
target: ts.ScriptTarget.Latest,
resolveIdFallback,
svelteOptions: {
hydratable: true,
generate: "dom",
},
}),
],
files: {
"/App.svelte": App,
"/index.ts": `
import App from './App.svelte';
new App({
target: document.querySelector("main"),
hydrate: true,
props: { foo: "hello" }
});
`,
},
});
const out2 = await bundled2.generate({ format: "iife" });
const code2 = out2.output[0].code;
fs.writeFileSync(
"test.html",
`<html>
<head>
<style>${css}</style>
</head>
<body>
<button onclick="hydrate()">hydrate</button>
<main>${html}</main>
<script>
function hydrate() {
/*<!--*/
${code2}
/*-->*/
}
</script>
</body>
</html>`
);
// out.output[0].code
}
main().catch(console.error);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment