ITADN

proposal to replace the default html tag

#2Closedgurgunday 创建于 2023-11-17
G
gurgundaycommented
Hey, just wanted to ask if you'd be down to integrating [my html tag](https://github.com/gurgunday/html) to `fastify-html` For very short strings it is 10x faster, for long strings it can be more than 700x faster It also supports html escaping **by default** – to indicate that an expression is safe to render raw, it must be prefixed with `!` I think people who are using React & Co. just to send basic html to users are making it much harder than necessary ## Random benchmark results (html2 is common-tags) ```bash html1 with safe input x 29,247,213 ops/sec ±0.79% (98 runs sampled) html1 with safe input x 22,540,186 ops/sec ±0.09% (91 runs sampled) html1 with safe input x 32,791,098 ops/sec ±0.10% (96 runs sampled) html1 with safe input x 10,819,679 ops/sec ±0.62% (99 runs sampled) html1 with safe input x 32,523,957 ops/sec ±0.43% (98 runs sampled) html2 with safe input x 41,971 ops/sec ±0.14% (98 runs sampled) html2 with safe input x 2,225,232 ops/sec ±0.20% (99 runs sampled) html2 with safe input x 3,117,999 ops/sec ±0.42% (96 runs sampled) html2 with safe input x 1,874,689 ops/sec ±0.23% (94 runs sampled) html2 with safe input x 3,090,945 ops/sec ±0.51% (97 runs sampled) ``` ## Benchmark ```js import benchmark from "benchmark"; import { html as html1 } from "./html.js"; import { html as html2 } from "common-tags"; // Define input data const dangerousOutputWithHTMLEscapeChars = "<script>".repeat(1000); const safeOutput = "This is safe content!".repeat(1000); // Create benchmark suite const suite = new benchmark.Suite(); // Add tests to the suite suite .add("html1 with safe input", () => { html1`<div>!${safeOutput}</div>`; }) .add("html1 with safe input", () => { html1`<div>!${123321}</div>`; }) .add("html1 with safe input", () => { html1`<div>!${undefined}</div>`; }) .add("html1 with safe input", () => { html1`<div>!${[null, 123, undefined]}</div>`; }) .add("html1 with safe input", () => { html1`<div>!${""}</div>`; }) .add("html2 with safe input", () => { html2`<div>!${safeOutput}</div>`; }) .add("html2 with safe input", () => { html2`<div>!${123321}</div>`; }) .add("html2 with safe input", () => { html2`<div>!${undefined}</div>`; }) .add("html2 with safe input", () => { html2`<div>!${[null, 123, undefined]}</div>`; }) .add("html2 with safe input", () => { html2`<div>!${""}</div>`; }) .on("cycle", function (event) { console.log(String(event.target)); }) .on("complete", function () { console.log("Fastest is " + this.filter("fastest").map("name")); }) // Run the benchmark .run({ async: true }); ``` ## A complex example Here's an example where the `html` tag can completely replace React's rendering model while natively supporting Prettier formatting, Tailwind completions, and all the other goodies ```js // layout.js const Layout = (it, View) => { return html`<!doctype html> <html lang="${it.user ? "" : "en"}" data-theme="${it.user?.data.theme || "blackHEYHEY"}" class="mx-auto max-w-[1440px] overflow-auto scroll-smooth bg-cover bg-center md:bg-fixed" > <head> !${Meta(it)} <link rel="stylesheet" href="/p/assets/css/style.min.css" /> <link rel="icon" sizes="192x192" href="/p/assets/img/lolo-192x192.png" /> <link rel="apple-touch-icon" sizes="192x192" href="/p/assets/img/lolo-192x192.png" /> !${it.scripts?.map((script) => { return html` <script fetchpriority="low" type="module" src="/p/assets/js/${script}" ></script> `; })} <script defer src="/p/assets/misc/js/quicklink.min.js"></script> !${it.pageBackground && it.user?.data.profileBG && it.user.data.profileBGLastUploadDate && it.user.data.isPro ? html` <style> html { background-image: url("${process.env .S3_CDN_URI}/userAssets/${it.user.id}/profileBG.webp"); } body { backdrop-filter: blur( ${it.user.data.profileBGBlur ?? "10"}px ); -webkit-backdrop-filter: blur( ${it.user.data.profileBGBlur ?? "10"}px ); } </style> ` : ""} !${it.user?.data.theme === "custom" ? html` <style> [data-theme=custom] { ${it.user.getThemeCustomResult()} } </style> ` : ""} </head> <body class="min-h-screen overflow-hidden"> <header> <nav class="navbar"> <div class="navbar-start"> <a href="/" class="btn btn-ghost text-lg font-black capitalize"> HEYHEY </a> </div> <div class="navbar-end"> !${it.sessionAccount ? html` <a href="/p/account/profile" class="btn btn-square btn-ghost" > <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" class="fill-current" > <title>Settings Icon</title> <path d="m2.344 15.271 2 3.46a1 1 0 0 0 1.366.365l1.396-.806c.58.457 1.221.832 1.895 1.112V21a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1v-1.598a8.094 8.094 0 0 0 1.895-1.112l1.396.806c.477.275 1.091.11 1.366-.365l2-3.46a1.004 1.004 0 0 0-.365-1.366l-1.372-.793a7.683 7.683 0 0 0-.002-2.224l1.372-.793c.476-.275.641-.89.365-1.366l-2-3.46a1 1 0 0 0-1.366-.365l-1.396.806A8.034 8.034 0 0 0 15 4.598V3a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v1.598A8.094 8.094 0 0 0 7.105 5.71L5.71 4.904a.999.999 0 0 0-1.366.365l-2 3.46a1.004 1.004 0 0 0 .365 1.366l1.372.793a7.683 7.683 0 0 0 0 2.224l-1.372.793c-.476.275-.641.89-.365 1.366zM12 8c2.206 0 4 1.794 4 4s-1.794 4-4 4-4-1.794-4-4 1.794-4 4-4z" ></path> </svg> </a> <a href="/${it.sessionAccount.id}" class="btn btn-square btn-ghost" > <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" class="fill-current" > <title>Home Icon</title> <path d="m21.743 12.331-9-10c-.379-.422-1.107-.422-1.486 0l-9 10a.998.998 0 0 0-.17 1.076c.16.361.518.593.913.593h2v7a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-4h4v4a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-7h2a.998.998 0 0 0 .743-1.669z" ></path> </svg> </a> ` : html` <a href="/p/login" class="btn btn-square btn-ghost"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" class="fill-current" > <title>Login Icon</title> <path d="M12 2C6.579 2 2 6.579 2 12s4.579 10 10 10 10-4.579 10-10S17.421 2 12 2zm0 5c1.727 0 3 1.272 3 3s-1.273 3-3 3c-1.726 0-3-1.272-3-3s1.274-3 3-3zm-5.106 9.772c.897-1.32 2.393-2.2 4.106-2.2h2c1.714 0 3.209.88 4.106 2.2C15.828 18.14 14.015 19 12 19s-3.828-.86-5.106-2.228z" ></path> </svg> </a> `} </div> </nav> </header> !${View(it)} !${it.user ? "" : html` <footer class="footer footer-center rounded p-16"> <div class="grid grid-flow-col gap-5"> <a href="mailto:hey@heyhey,to" class="link-hover link"> Contact </a> <a href="/p/privacy" class="link-hover link">Privacy</a> <a href="/p/terms" class="link-hover link">Terms</a> </div> <div> <p>&copy; GOODMEN VENTURES, Inc.</p> </div> </footer> `} </body> </html>`; }; ```
关闭于 2023-11-22 3 条评论