Skip to content

Instantly share code, notes, and snippets.

@mizchi
Last active July 30, 2019 10:01
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/e928b223dbce3a17e80d6d1a843ea8c0 to your computer and use it in GitHub Desktop.
Save mizchi/e928b223dbce3a17e80d6d1a843ea8c0 to your computer and use it in GitHub Desktop.
import { h } from "preact";
import { useState, useEffect } from "preact/hooks";
import renderPreactToString from "preact-render-to-string";
import ts from "typescript";
import * as rollup from "rollup";
import virtual from "rollup-plugin-virtual";
async function renderToString(component: any, props: any) {
return renderPreactToString(h(component, props));
}
async function compile(jsSource: string, props: any) {
const tsCompiled = ts.transpileModule(jsSource, {
compilerOptions: {
target: ts.ScriptTarget.ES5,
module: ts.ModuleKind.ES2015,
jsx: ts.JsxEmit.React,
jsxFactory: "h"
}
});
const bundle = await rollup.rollup({
input: "index.js",
plugins: [
virtual({
"index.js": tsCompiled.outputText,
preact: `
export const h = __helpers.h;
`,
// preact: preactSource,
"preact/hooks": `
export const useState = __helpers.useState;
export const useEffect = __helpers.useEffect;
`
})
]
});
const out = await bundle.generate({
format: "iife",
sourcemap: false,
name: "$$out"
});
const code = out.output[0].code;
const expr = code.replace("var $$out =", "");
const func = new Function("__helpers", "return " + expr);
const CompiledComponent = func({ h, useEffect, useState });
const html = await renderToString(CompiledComponent, props);
console.log("html", html);
return {
html,
props,
code: expr
};
}
const sampleSource = `
/** @jsx h */
import { h } from "preact";
import { useState, useEffect } from "preact/hooks";
export default (props: { count: number }) => {
const [value, setValue] = useState(0);
useEffect(() => {
const id = setInterval(() => {
setValue(value + 2);
}, 1000);
return () => clearInterval(id);
}, [value]);
return (
<div>
hello, {props.count}
</div>
);
}
`;
compile(sampleSource, { count: 3 }).then(ret => {
console.log(ret);
});
// {"html":"<div>hello, 3</div>","props":{"count":3},"code":" (function () {\n 'use strict';\n\n const h = __helpers.h;\n\n const useState = __helpers.useState;\n const useEffect = __helpers.useEffect;\n\n /** @jsx h */\n var _virtual_index = (function (props) {\n var _a = useState(0), value = _a[0], setValue = _a[1];\n useEffect(function () {\n var id = setInterval(function () {\n setValue(value + 2);\n }, 1000);\n return function () { return clearInterval(id); };\n }, [value]);\n return (h(\"div\", null,\n \"hello, \",\n props.count));\n });\n\n return _virtual_index;\n\n}());\n"}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment